JAVA

[JAVA]JAVA Annotaion (+Lombok제공 Annotaion 정리)

johye0 2022. 2. 6. 18:45
반응형

Java Annotation?


자바 어노테이션은 자바 소스코드에 추가하여 사용할 수 있는 메타데이터의 일종이다. JDK 1.5 버전 이상부터 사용 가능하며, 보통 @ 기호를 앞에 붙여서 사용한다.

자바 어노테이션은 클래스파일에 임베디드 되어 컴파일러에 의해 생성된 후, 자바 가상 머신에 포함되어 작동한다.

💡 메타데이터(metadata):
데이터(data)에 대한 데이터, 어떤 목적을 가지고 만들어진 데이터 (Constructed data whit a purpose) 애플리케이션이 처리할 데이터가 아니라, 컴파일 과정과 실행 과정에서 코드를 어떻게 컴파일하고 처리할 것인지 알려주는 정보

 

Annotation의 용도

  1. 컴파일러에게 코드 문법 에러를 체크하도록 정보를 제공함.
  2. 소프트웨어 개발 툴(IDE)이 빌드 또는 배치 시 코드를 자동으로 생성할 수 있도록 정보를 제공함.
  3. 코드 실행 시(런타임 시) 특정 기능을 실행하도록 정보 제공

 

내장 Annotation

자바는 언어에 내장된 어노테이션들의5집합을 정의한다. 10개의 표준 어노테이션 중에 5개가 java.lang의 일부이며, 나머지 7개는 java.lang.annotation으로부터 가져온다.

  • 자바 코드에 적용되는 내장 어노테이션:
    • @Deprecated: 사용하면 위험한 코드임을 표시하거나, 해당 코드보다 개선된 코드가 존재하기 때문에 사용하지 말 것을 알리기 위해 사용@SafeVarargs: 자바 7부터 추가, 생성자나 메서드의 가변 인자 파라미터가 안전하게 사용된다는 것을 나타내기 위해 사용
    • @FunctionalInterface: 자바 8부터 추가, 인터페이스를 함수형 프로그래밍인 람다 방식으로 사용하기를 추천하는 용도로 사용
    • @SuppressWarnings: 이미 인지한 컴파일러의 경고를 제거하기 위해 사용
    • @Override: 상위 타입에 정의된 메소드를 재정의했다는 것을 알리기 위해 사용
  • 메타 어노테이션: 커스텀 어노테이션 작성 시 어노테이션을 설명하기 위한 메타 어노테이션
    • @Documented: javadoc 및 기타 문서 툴에 의해 문서화될 때, 해당 어노테이션이 문서에 표시된다.@Inherited: 자식 클래스에서 부모 클래스에 선언된 어노테이션을 상속받을 때 사용
    • @Repeatable: 자바 7부터 추가, 동일한 위치에 같은 어노테이션을 여러 개 선언할 수 있게 함.
    • @Target: 어노테이션 적용 가능한 대상 지정
    • @Retention: 어노테이션 유지 범위 지정
    • @Override 예제
    • public class Animal {
          public void speak() {
          }
      
          public String getType() {
              return "Generic animal";
          }
      }
      
      public class Cat extends Animal {
          @Override
          public void speak() { // This is a good override.
              System.out.println("Meow.");
          }
      
          @Override
          public String getType() { // Compile-time error due to mistyped name.
              return "Cat";
          }
      }

 

Meta Annotation


커스텀 어노테이션 작성 시 어노테이션을 설명하기 위한 것으로, 5개가 존재한다.

@Target

어노테이션을 적용할 수 있는 대상(위치)를 나타내는 어노테이션. 만약, Target에 선언된 대상과 다른 대상에 어노테이션을 적용할 경우 컴파일 에러가 발생한다.

적용 대상은 java.lang.annotation.ElementType 열거 상수로, 아래와 같이 정의되어 있다.

  • TYPE : class, interface, annotation, enum에 적용
  • FIELD : 필드, enum 상수에 적용
  • METHOD : 메소드에 적용
  • PARAMETER : 파라미터에 적용
  • CONSTRUCTOR : 생성자에 적용
  • LOCAL_VARIABLE : 지역변수에 적용
  • ANNOTATION_TYPE : 어노테이션에 적용
  • PACKAGE : 패키지에 적용
  • TYPE_PARAMETER : 자바 8부터 추가, 타입 파라미터에 적용
  • TYPE_USE : 자바8부터 추가, JLS의 15가지 타입과 타입 파라미터에 적용

[사용 예시]

// 필드에만 MyCustom 어노테이션 적용 가능
@Target(ElementType.FIELD)
public @interface MyCustom {}

// 필드와 메소드에만 MyCustom 어노테이션 적용 가능
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface MyCustom {}

 

@Retention

사용 용도에 따라 어노테이션이 어느 시점까지 유지되는가를 지정하는 어노테이션으로, 생략될 경우 RetentionPolicy.CLASS 가 적용된다.

어노테이션 유지 정책은 java.lang.annotation.RetentionPolicy 열거 상수로, 아래와 같이 정의되어 있다.

  • SOURCE : 소스상에서만 어노테이션을 유지한다. 컴파일 시점에는 어노테이션이 의미가 없어진다.
  • CLASS : 소스, class파일(바이트코드 파일)까지 적용된다.
  • RUNTIME : 소스, class파일뿐만 아니라 JVM에서 실행될 때도 적용되어 런타임 시 리플렉션으로 어노테이션 정보를 얻을 수 있다.
💡리플렉션 (Reflection):
런타임시에 클래스의 메타정보를 얻는 기능 ⇒ 클래스가 가진 필드, 생성자, 메서드, 적용된 어노테이션이 무엇인지 알아내는 것

 

[사용 예시]

// 클래스 파일에 기록될 뿐만 아니라 실행시에도 JVM에 적재돼 유지됨
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {}

// 런타임시 유지될 수 있도록 어노테이션이 적용된 클래스의 바이트 코드에 RuntimeVisibleAnnotations이 기록되어 있습니다.
> javap -v MyClass 
...중략...
Constant pool:
...중략...
  #10 = Utf8               RuntimeVisibleAnnotations
  #11 = Utf8               LMyAnnotation;
...중략...

 

@Inherited

부모클래스에 선언된 어노테이션이 자식 클래스에 상속된다.

[사용 예시]

// 1. 어노테이션 2개 작성
@Retention(RetentionPolicy.RUNTIME)
@interface NonInheritedAnnotation {}

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@interface InheritedAnnotation {}

// 2. 클래스 작성
@NonInheritedAnnotation
class A {}

@InheritedAnnotation
class B extends A {}

class C extends B {}

[결과]

// 1. NonInheritedAnnotation 존재 여부 확인
System.out.println("Non inherited A : " + new A().getClass().getAnnotation(NonInheritedAnnotation.class));
System.out.println("Non inherited B : " + new B().getClass().getAnnotation(NonInheritedAnnotation.class));
System.out.println("Non inherited C : " + new C().getClass().getAnnotation(NonInheritedAnnotation.class));

Non inherited A : @NonInheritedAnnotation()
Non inherited B : null
Non inherited C : null

// 2. InheritedAnnotation 존재 여부 확인
System.out.println("inherited A : " + new A().getClass().getAnnotation(InheritedAnnotation.class));
System.out.println("inherited B : " + new B().getClass().getAnnotation(InheritedAnnotation.class));
System.out.println("inherited C : " + new C().getClass().getAnnotation(InheritedAnnotation.class));

inherited A : null
inherited B : @InheritedAnnotation()
inherited C : @InheritedAnnotation()

 

@Repeatable

동일한 어노테이션을 여러 개 선언할 수 있도록 하는 어노테이션이다.

[사용 예시]

@Repeatable(Roles.class) // 컴파일시 Roles에 여러 개의 Role을 컴파일러가 저장
@interface Role {
  String value();
}

@interface Roles {
  Role[] value();
}

@Role("Role1")
@Role("Role2")
class Repeat {}

 

 

Lombok Annotation


@NoArgsConstructor

: 기본생성자를 자동으로 추가한다.

  ⇒ Entity Class를 프로젝트 코드상에서 기본 생성자로 생성하는 것은 금지하고,

     JPA에서 Entity 클래스를 생성하는것은 허용하기 위해 추가

 

@AllArgsConstructor

: 모든 필드 값을 파라미터로 받는 생성자를 추가

 

@RequiredArgsConstructor

: final이나 @NonNull인 필드 값만 파라미터로 받는 생성자를 추가

 

@Getter

@Setter

 

@ToString

: Class 내 모든 필드의 toString method를 자동 생성

 

@EqualsAndHashCode

: equals와 hashCode method를 오버라이딩 해주는 Annotation

 

@Builder

: 어느 필드에 어떤 값을 채워야 할지 명확하게 정하여 생성 시점에 값을 채워준다.

 

@Data

: @Getter @Setter @EqualsAndHashCode @AllArgsConstructor을 포함 ⇒ 실제로 사용하지 않는 것이 좋다.

반응형