어노테이션
어노테이션이란?
어노테이션은 자바 1.5부터 추가된 요소로 사전적 의미로는 주석을 의미한다. 하지만 자바에서는 단순 주석이 아닌 클래스에 특수한 의미를 부여하거나 기능을 주입하기 위한 메타데이터라고 볼 수 있다. 어노테이션은 인터페이스 일종으로 @를 사용하여 선언한다. 전에 JUNIT 테스트시 사용하는 @Test도 어노테이션이다. 단지 이게 테스트해야한다는 것을 프로그램에게 알리는 역할을 할 뿐, 메서드가 포함된 프로그램에는 아무런 영향을 미치지 않는다.
어노테이션의 용도
- 컴파일러에게 코드 문법 에러를 체크하도록 정보를 제공
- 인텔리제이 같은 소프트웨어 개발 툴이 빌드나 배치 시 코드를 자동으로 생성할 수 있도록 정보를 제공
- 런타임 시 특정기능을 실행하도록 정보를 제공
어노테이션의 종류
- Built-in Annotation: 자바에서 기본으로 제공하는 어노테이션
- Meta Annotation: 커스텀 어노테이션을 만들 수 있게 제공된 어노테이션
어노테이션 정의
커스텀 어노테이션을 만들려면 @interface [생성할 어노테이션 이름] 의 형태로 어노테이션을 정의해야한다. 어노테이션을 정의할 때, 생성되는 어노테이션에 대한 메타 어노테이션은 어노테이션 정의 앞쪽에 붙여준다.
예시
MyAnnotation
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "MyAnnotation : default value";
}
MyObject
public class MyObject {
@MyAnnotation
public void testMethod1() {
System.out.println("This is testMethod1");
}
@MyAnnotation(value = "Custom Value")
public void testMethod2() {
System.out.println("This is testMethod2");
}
}
Main
public class Main {
public static void main(String[] args) {
//리플렉션을 사용하여 MyObject 클래스의 메서드 정보를 가져온다
Method[] methodList = MyObject.class.getMethods();
for (Method method : methodList) {
if(method.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation annotation=method.getDeclaredAnnotation(MyAnnotation.class);
String value=annotation.value();
System.out.println(method.getName() + ":" + value);
}
}
}
}
Built-in Annotation
기본으로 제공되는 어노테이션
종류
|
설명
|
@Override
|
컴파일러에게 오버라이딩하는 메서드라는 것을 알린다 |
@Deprecated
|
앞으로 사용하지 않을 것을 권장하는 대상에 붙인다
|
@SuppressWarnings
|
컴파일러 특정 경고메시지가 나타나지 않게 해준다
|
@SafeVarargs
|
자바 1.7이상부터 사용가능하며 제네릭스 타입의 가변인자에 사용한다
|
@FunctionalInterface
|
자바 1.8이상부터 사용가능하며 함수형 인터페이스 라는 것을 알린다
|
출처: 자바의 정석
Override
- 메서드 앞에만 붙일 수 있는 에너테이션, 조상의 메서드를 오버라이딩하는 것이라는 걸 컴파일러에게 알려주는 역할을 함
- 이제 상속받은 자식 클래스에서 메서드를 잘못 적어도 컴파일러는 그저 새로운 이름의 메서드가 추가 된지알음 → Override어노테이션을 통해 컴파일러는 부모에 이 메서드가 존재하는지 유무를 파악함 (한마디로 실수방지)
Deprecated
- 새로운 버전의 JDK가 소개될때, 안쓰거나 대체된 기능들이 존재하는데 그러한 필드나 메서드에 Deprecated어노테이션을 붙여 다른 대상으로 대체되거나 더 이상 사용되지않는 다는것을 의미한다.
- 사용해도 문제는 없다(권장일뿐 강제성은 없기때문이다)
- 관련해서 Deprecated 메서드들 정리되어있는글 한번 보기
- 예시
- 전에 쓰레드 공부할때 suspend, destroy, resum, stop 메서드가 더이상 사용하지 않는 메서드여서 어노테이션으로 명시되어있다
FunctionalInterface
- 함수형 인터페이스 선언시 사용, 컴파일러가 함수형 인터페이스를 올바르게 선언했는지 확인, 잘못된 경우 에러 발생
- 따라서 함수형 인터페이스를 선언할대 꼭 붙여주자
※함수형 인터페이스- 5가지가 존재한다
- Consumer
- Supplier
- Function
- Operator
- Predicated
- 5가지가 존재한다
SuppressWarnings
- 컴파일러가 보여주는 경고메시지가 나타나지 않게 억제해준다, 한마디로 경고가 발생할 것을 알면서도 묵인해야할때 사용한다
- 주로 사용되는 것은 “deprecation”, “unchecked”, “rawtypes”, “varags”정도가 있다
경고 사용되는 예시
public class Main {
public static void main(String args[]){
Thread th = new Thread();
th.start();
th.run();
th.stop();
}
}
public class Main {
@SuppressWarnings("deprecation")
public static void main(String args[]){
Thread th = new Thread();
th.start();
th.run();
th.stop();
}
}
추가하면 경고가 없어진것을 확인 할 수 있다.
Safe Varags
이것을 알기전에 하나 알고가야한다, 추가로 이 애너테이션은 static 이나 final이 붙은 메서드와 생성자에만 붙일 수 있음
- Reifiable Type
Java에서 Runtime시에 완전하게 오브젝트 정보를 표현할 수 있는 타입을 가르켜 Reifiable 하다고 합니다.Reifiable 가능한 타입 정보는 다음과 같습니다.- 원시 타입(int, double, float, byte 등등)
- Number, Integer와 같은 일반 클래스와 인터페이스 타입
- Unbounded Wildcard가 포함된 Parameterized Type(List<?>, ArrayList<?> 등)
- Raw Type(List, ArrayList, Map 등)
- 이제 메서드에 선언된 가변자의 타입이 non-reifiable타입의 경우, 한마디로 컴파일시에 정보가 제거된 유형이다.
public class Main { public static <T> void myMethod(T... args) { //제너릭 사용 } public static void main(String[] args) { List<String> myList = new ArrayList<>(); // 경고 발생: non-reifiable 타입인 제네릭 배열을 가변인자로 전달 myMethod(myList.toArray(new String[0])); } }
해결법
public class Main {
@SafeVarargs
public static <T> void myMethod(T... args) { //제너릭 사용
}
public static void main(String[] args) {
List<String> myList = new ArrayList<>();
// 경고 발생: non-reifiable 타입인 제네릭 배열을 인자로 전달
myMethod(myList.toArray(new String[0]));
}
}
Meta Annotation
정확한 의미는 어노테이션을 위한 에너테이션, 즉 어노테이션 붙이는 어노테이션으로 어노테이션 을 정의할때 어노테이션 의 적용대상이나 유지기간등을 지정하는데 사용된다.
간략하게 말하면 커스텀 어노테이션을 만들 수 있게 제공된 어노테이션이다
종류
|
설명
|
@Retention
|
어노테이션이 유지되는 범위를 지정하는데 사용된다
|
@Documented
|
어노테이션 정보를 javadoc으로 작성된 문서에 포함되게 한다
|
@Target
|
어노테이션이 적용할 위치를 지정합니다. 여러 값일 경우 {} 사용
|
@Inherited
|
어노테이션이 자손 클래스에 상속되도록 한다 |
@Repeatable
|
자바 1.8이상부터 사용가능하며 에노테이션을 반복해서 적용할 수 있게 한다 |
출처: 자바의 정석
Retention
- 에너테이션이 유지되는 기간 지정하는데 사용
- 세가지 유지정책
- RetentionPolicy.Source: 컴파일 전까지만 유효
- RetentionPolicy.CLASS: 컴파일러가 클래스를 참조할 때까지 유효
- RetentionPolicy.RUNTIME: 컴파일 이후에도 JVM에 의해 계속 참조 가능
Built-in Annotation중 하나인 Deprecated의 자바 문서를 보면 컴파일 이후에도 계속 참조가능하도록 RUNTIME으로 유지정책이 되어있는것을 볼 수 있다
Target
Target은 어노테이션이 적용될 위치를 지정하는 어노테이션이다.
종류
- ElementType.PACKAGE: 패키지선언
- ElementType.TYPE: 타입선언
- ElementType.ANNOTATION_TYPE: 어노테이션 타입
- ElementType.CONSRTUCTOR: 생성자 선언
- ElementType.FIELD: 멤버 변수 선언
- ElementType.LOCAL_VARIABLE: 지역 변수 선언
- ElementType.METHOD: 메서드 선언
- ElementType.PARAMETER: 전달인자 선언
- ElementType.TYPE_PARAMETER: 전달인자 타입 선언
- ElementType.TYPE_USE: 타입선언
아래 예시처럼 적용될 위치를 설정해주면 된다
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "MyAnnotation : default value";
}
Documented
- 해당 어노테이션을 javadoc 파일에 추가시킬지 여부이다.
/**
* MyAnnotation
* add javadoc for helping to explain documented
*
*/
@Documented
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "MyAnnotation : default value";
}
위와 같이 Documented 출력하고 인텔리제이에서 Tools -> Generated javadoc 하게되면
아래와 같이 공식 문서처럼 출력된다
생성 과정 관련해서는 아래 블로그를 참고하면 편하다
https://babgeuleus.tistory.com/105
어노테이션 프로세서
- 어노테이션 프로세스는 Java 소스 코드 및 클래스 파일에서 어노테이션 정보를 추출하고 이를 활용하여 추가 작업을 수행하는 자동화된 프로세스입니다.
- 컴파일 시간에 실행되며, 컴파일러가 소스 코드를 처리하는 동안 어노테이션 정보를 검사한다.
- 주로 코드 생성, 코드 검증, 설정 파일 생성 및 기타 자동화 작업을 수행하는데 사용된다.
- 예시로는 Override와 Lombok 라이브러리 등이 있다.
아래 링크로 들어가면 더 자세한 설명과 함께 특정 Annotation을 사용하는 클래스는 변경할 때마다 그대로 적용이 되어 Maven Compile을 안하도록 설정하는 상세한 방법이 나와있다. -> 예시로 따로 소스코드에 getter 및 setter함수를 개발자가 직접 만들지 않고 setName, getName등의 함수를 쓸 수 있다
어노테이션 프로세스를 통해 메타프로그래밍 기법을 활용하여 보다 유연하고 효율적인 소프트웨어 개발이 가능해진다
출처
자바의 정석(저자:남궁성)
https://blog.naver.com/swoh1227/222229853664
'자바(Java)' 카테고리의 다른 글
[자바] 제네릭(Generic) (1) | 2023.11.02 |
---|---|
[자바] 자바 I/O (1) | 2023.10.14 |
[자바] 자바 Enum (0) | 2023.09.27 |
[자바] 자바 멀티쓰레드 프로그래밍 (0) | 2023.09.21 |
[자바] 자바 예외처리 (0) | 2023.09.14 |