Java | Android

롬복(Lombok)의 어노테이션들 - (EqaulsAndHashCode, XArgsConstructor, Data, Value, Builder)

partner_jun 2017. 5. 31. 11:12

6. @EqualsAndHashCode

equals(Object) 메소드와 hashCode() 메소드를 오버라이드한다.  @ToString 어노테이션과 마찬가지로 exclude 파라미터로 필드를 제외하거나 callSuper 파라미터로 부모 객체를 생략하거나 포함할 수 있다. 또, 필드에 객체 직렬화(Serializable)에서 제외할때 사용하는 transient 키워드를 사용하면 exclude 파라미터로 입력한 것과 같이 두 메소드에서 제외된다.

@EqualsAndHashCode(exclude = "value")
private static class LombokClass1 {
private String name = "lombok";
@Setter
private int value;
}

@EqualsAndHashCode
private static class LombokClass2{
private String name = "lombok";
@Setter
private int value;
}
val l1 = new LombokClass1();
l1.setValue(100);
System.out.println(l1.hashCode()); // -1097163153

val l2 = new LombokClass1();
l2.setValue(500);
System.out.println(l2.hashCode()); // -1097163153

val result = l1.equals(l2);
System.out.println(result); // true
val l3 = new LombokClass2();
l3.setValue(100);
System.out.println(l3.hashCode()); // -308116487

val l4 = new LombokClass2();
l4.setValue(500);
System.out.println(l4.hashCode()); // -308116087

val result2 = l3.equals(l4);
System.out.println(result2); // false


lombok.config 파일에서 

lombok.equalsAndHashCode.doNotUseGetters = false

설정을 통해 오버라이드된 equals(), hashCode() 메소드가 각 필드의 Getter를 사용할지 여부를 설정할 수 있다.




7. @NoArgsConstructor / @AllArgsConstructor / @RequiredArgsConstructor

클래스의 생성자를 만들어준다. 세 종류를 중복해서 사용할 수 있으며 어노테이션 이름 그대로 @NoArgsConstructor는 파라미터가 없는 생성자, @AllArgsConstructor는 모든 필드를 파라미터로 가지는 생성자를 만든다. @RequiredArgsConstrucotr는 기본 값이 없고 @NonNull 어노테이션이 붙은 필드를 파라미터로 입력받는 생성자를 만든다..

이 세 가지 생성자를 만드는 어노테이션 모두 객체를 만드는 static 메소드의 이름을 입력받는 staticName, 생성자의 접근제한자를 설정하는 access를 파라미터로 입력할 수 있다.

@NoArgsConstructor
@AllArgsConstructor(staticName = "of")
@RequiredArgsConstructor
@ToString
public static class LombokClass {
private String name = "lombok";
@NonNull private int value;
@NonNull private int value2;
}
val requiredArgs = new LombokClass(100, 200);
System.out.println(requiredArgs); // LombokClass(name=lombok, value=100, value2=200)

val noArgs = new LombokClass();
System.out.println(noArgs); // LombokClass(name=lombok, value=0, value2=0)

val allArgs1 = LombokClass.of("Hello", 500, 600);
val allArgs2 = new LombokClass("World", 900, 1000);
System.out.println(allArgs1); // LombokClass(name=Hello, value=500, value2=600)
System.out.println(allArgs2); // LombokClass(name=World, value=900, value2=1000)


또, 안드로이드에서는 lombok.config 파일에

lombok.anyConstructor.suppressConstructorProperties = true

설정이 되어있어야 정상적으로 컴파일된다. @java.beans.ConstructorProperties 어노테이션이 자동으로 추가되지 않게 하는 설정이다.




8. @Data

롬복에서 가장 중요한 어노테이션 중 하나다. 앞서 살펴본 @ToString, @EqualsAndHashCode, @Getter/@Setter, @RequiredArgsConstructor 어노테이션을 모두 사용한 것과 같은 효과를 준다. 하지만 세부 설정을 하려면 각각의 어노테이션을 붙여야 한다는 점, @RequiredArgsConstructor 어노테이션으로 만들어지는 생성자는 다른 생성자가 없을 때에만 만들어진다는 점을 주의해야 한다.

@AllArgsConstructor
@Data(staticConstructor = "of")
public static class LombokClass {
private String name = "lombok";
@NonNull private int value;
@NonNull private int value2;
}
// val lombokClass = LombokClass.of(100, 200); // of 메소드가 만들어지지 않음
// System.out.println(lombokClass);

val lombokClass1 = new LombokClass("Hello", 100, 200);
System.out.println(lombokClass1); // LombokClass(name=Hello, value=100, value2=200)

val lombokClass2 = new LombokClass("Hello", 100, 200);
val result = lombokClass1.equals(lombokClass2);
System.out.println(result); // true




9. @Value

@Data 어노테이션과 비슷하지만 필드를 변경할 수 없는 '불변 객체'가 만들어진다. 필드에 @Wither 어노테이션을 이용하면 with필드명(값) 메소드가 만들어지는데, 이 메소드를 이용하면 값을 변경한 새로운 객체를 만들어준다. 값을 변경하지 않는 프로그래밍에서 아주 유용하게 활용된다.

@Value
@ToString(exclude = "name")
public static class LombokClass {
@Wither(AccessLevel.PROTECTED)
private String name;
private int value;
private int value2;
}
val lombokClass = new LombokClass("Hello", 200, 500);
System.out.println(lombokClass); // LombokClass(value=200, value2=500)

val lombokClass2 = lombokClass.withName("World");
System.out.println(lombokClass2); // LombokClass(value=200, value2=500)

val result = lombokClass.equals(lombokClass2);
System.out.println(result); // false


@Value 어노테이션은 val 어노테이션을 사용하기 때문에 val 어노테이션이 사용가능한 상태에서만 @Value 어노테이션도 사용이 가능하다.




10. @Builder

빌더 패턴을 적용한 객체 생성 메소드/클래스를 만들어준다.

builderClassName 파라미터로 nested 빌더 클래스의 이름을 (클래스명Builder가 기본), 

builderMethodName으로 빌더 클래스를 반환하는 static 메소드의 이름을 (builder()가 기본), 

buildMethodName으로 객체를 반환하는 빌드 메소드의 이름 (build()가 기본)을 설정할 수 있다.


필드에 @Builder.Default 어노테이션을 붙여 기본 값을 설정할 수 있고,

@Singular 어노테이션을 붙여 빈 collection을 자동으로 만들 수 있다. @Singluar 어노테이션은 파라미터로 builder에서 값을 추가할 때 사용되는 메소드의 이름을 입력받는다. 또, @Singular 어노테이션으로 만들어진 collection은 수정할 수 없다.


@Builder
@ToString
public static class LombokClass {
private String name;
private int value;
@Builder.Default private int value2 = 999; // 기본 값 설정
@Singular("addVal") private List<Integer> values;
}
val lombokClass = LombokClass.builder()
.name("Hello")
.value(500)
.addVal(100)
.addVal(200)
.addVal(300)
.build();

System.out.println(lombokClass); // LombokClass(name=Hello, value=500, value2=999, values=[100, 200, 300])


val val0 = lombokClass.values.get(0);
System.out.println(val0); // 100


// lombokClass.values.clear(); // Exception in thread "main" java.lang.UnsupportedOperationException
// System.out.println(lombokClass);