-
Java 애너테이션Java 2024. 2. 26. 16:53728x90반응형
애너테이션이란?
자바를 개발한 사람들은 소스코드에 대한 문서를 따로 만들기보다, 소스코드와 문서를 하나의 파일로 관리하는 것이 낫다고 생각했다.
소스코드의 주석에 소스코드에 대한 정보를 저장하고, 소스코드의 주석으로부터 HTML 문서를 생성해내는 프로그램(javadoc.exe)을 만들어서 사용했다
이 기능을 이용해서, 프로그램의 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것이다.
자신이 작성한 소스코드 중 특정 메서드만 테스트하고 싶으면, @TEST라는 애너테이션을 메서드 앞에 붙인다.@TEST public void method(){ ~~~ }
모든 프로그램에 의미가 있지는 않고, 해당 프로그램에 미리 정의된 종류와 형식으로 작성해야만 의미가 있다.
@TEST는 테스트 프로그램을 제외한 다른 프로그램에는 아무 의미가 없다
JDK에서 기본 제공하는 표준 애너테이션은 주로 컴파일러를 위한 것이다.
java.lang.annotation패키지에 포함되어 있다.표준 애너테이션
override
메서드 앞에만 붙일 수 있는 애너테이션으로, 조상의 메서드를 오버라이딩하는 것이라는 걸 컴파일러에게 알려주는 역할
class Parent{ void parentMethod(){} } class Child extends Parent{ void parent'm'ethod(){} }
위 오버라이딩 상황에서 컴파일러는 뭐가 잘못된 것인지 모른다.
그저 새로운 이름의 메서드가 추가된 것으로 인지한다.
그러나 메서드 앞에 @override라고 쓰면, 컴파일러가 같은 이름의 메서드가 조상에 있는지 확인하고,
없으면 에러를 출력한다.
필수는 아니지만 붙이면 실수를 방지할 수 있다.Deprecated
새로운 버전의 jdk가 나올 때, 새 기능이 추가될 뿐 아니라, 기존의 부족한 기능들을 개선하기도 한다.
기존의 기능을 대체할 것들이 추가되도, 이미 여러 곳에 사용되고 있을지 모르는 기존의 것들을 함부로 삭제할 수 없다.
그래서 생각한 방법이 더 이상 사용되지 않는 필드나 메서드에 @Deprecated를 붙인다.
이 애너테이션이 붙은 대상은 다른 것으로 대체되었으니 더 이상 사용하지 않는 것을 권장한다는 의미
다만, 권유일 뿐, 강제성은 없다Funcionallnterface
함수형 인터페이스를 선언할 때, 이걸 붙이면 컴파일러가 올바르게 선언했는지 확인하고, 아니면 에러를 발생시킨다.
필수는 아니지만 붙이면 실수를 방지할 수 있다.
SuppressWarnings
컴파일러가 보여주는 경고메시지가 나타나지 않게 억제한다.
경우에 따라 경고가 발생할 것을 알면서도 묵인해야 할 때, 그대로 두면 컴파일할 때마다 메세지가 나타난다.
컴파일러는 경고의 자세한 내용은 보여주지 않으므로 다른 경고들을 놓치기 쉽다.@SuppressWarnings("unchecked")
여러개는@SuppressWarnings({"unchecked", 'deprecation'})
경고 메세지의 종류는 jdk 버전이 올라가면 계속 추가되기 때문에 종류를 알아야 억제하는데,
-Xlint옵션으로 컴파일해서 나타나는 경고의 내용 중에 []안에 있는 것이 메세지의 종류이다.C:\ ~~~ > javac -Xlint AnnotationTest.java AnnotationTest.java:15: warning: [rawtypes] found raw type: List public static void sort(List list)
위 메세지를 없애기 위해 아래처럼 한다@SuppressWarnings("rawtypes") public static void sort(List list){ ~~~~ }
SafeVarargs
static이나 final이 붙은 메서드와 생성자에만 붙일 수 있다. 즉, 오버라이드될 수 있는 메서드에는 사용할 수 없다.
메서드에 선언된 가변인자의 타입이 non-reifiable타입일 경우, 해당 메서드를 선언하는 부분과 호출하는 부분에서 unchecked경고 발생
코드에 문제가 없다면 경고 억제를 위해 @SafeVarargs를 사용한다
지네릭스처럼 어떤 타입들은 컴파일 이후 제거된다.
컴파일 후에도 제거되지 않는 타입을 reifiable타입이라 하고, 제거되는 타입을 non-reifiable타입이라 한다
메서드를 선언할 때, SafeVarargs를 붙이면 메서드를 호출하는 곳의 경고도 억제된다
하지만 SuppressWarnings는 호출 시에도 애너테이션을 따로 붙여야 한다
그리고, SafeVarargs로 unchecked는 억제할 수 있지만 varargs 경고는 억제할 수 없기 때문에,
습관적으로 @SafeVarargs와 @SuppressWarnings("varargs")를 같이 쓴다메타 애너테이션
에너테이션을 위한 에너테이션
에너테이션을 정의할 때, 애너테이션의 적용대상이나, 유지기간 등을 지정하는데 사용된다
Target
애너테이션이 적용가능한 대상을 지정하는데 사용된다
Retention
애너테이션이 유지되는 기간을 지정
유지 정책
SOURCE : 소스 파일에만 존재. 클래스 파일에는 존재하지 않음
CLASS : 클래스 파일에 존재. 실행시에 사용불가. 기본값
RUNTIME : 클래스 파일에 존재. 실행 시에 사용 가능
@override나 @SuppressWarnings처럼 컴파일러가 사용하는 건 정책이 SOURCE다.
컴파일러를 직접 사용할 게 아니면 이 정책은 필요없다
RUNTIME은 실행 시에 리플렉션을 통해 클래스 파일에 저장된 애너테이션 정보를 읽어서 처리할 수 있다.
@Funcionallnterface는 컴파일러가 체크해주는 애너테이션이지만, 실행 시에도 사용되므로 RUNTIME이다.
CLASS는 컴파일러가 애너테이션 정보를 클래스 파일에 저장할 수 있게는 하지만,
클래스 파일이 JVM 에 로딩될 때는 애너테이션의 정보가 무시되어 실행 시에 애너테이션의 정보를 얻을 수 없다.
이런 이유로 기본값임에도 불구하고 CLASS는 잘 사용되지 않는다.
참고 지역 변수에 붙은 애너테이션은 컴파일러만 인식할 수 있으므로,
유지정책이 RUNTIME인 애너테이션을 지역변수에 붙여도 실행 시에는 인식되지 않는다
Documented
애너테이션에 대한 정보가 javadoc로 작성한 문서에 포함되도록 한다.
자바의 기본 제공 애너테이션 중에 @override와 @SuppressWarnings를 제외하고 모두 이 메타 애너테이션이 붙어 있다.
Inherited
애너테이션이 자손 클래스에 상속되도록 한다.
조상 클래스에 @Inherited를 붙이면, 자손에도 붙는다.
@Repeatable
보통은 한 대상에 한 종류의 애너테이션을 붙이는데,
Repeatable이 붙은 애너테이션은 여러번 붙일 수 있다.
@Native
네이티브 메서드에 의해 참조되는 상수 필드에 붙이는 애너테이션이다.
네이티브 메서드는 JVM이 설치된 OS의 메서드를 말한다.
네이티브 메서드는 보통 C언어로 작성되어 있는데, 자바에서는 메서드의 선언부만 정의하고 구현은 하지 않는다.그래서 추상메서드처럼 선언부만 있고 몸통이 없다.
모든 클래스의 조상인 Object 클래스의 메서드들은 대부분 네이티브 메서드이다.
네이티브 메서드는 자바로 정의되어 있기 때문에 호출하는 방법은 자바의 일반 메서드와 같지만,실제로 호출되는 것은 OS의 메서드이다.
아무 내용 없는 네이티브 메서드를 선언해 놓고 호출한다고 되는 것은 아니고,자바에 정의된 네이티브 메서드와 OS의 메서드를 연결해주는 작업이 추가로 필요하다.
이 역할은 JNI(java natice Interface)가 한다.
애너테이션 타입 정의
@interface 애너테이션이름{ 타입 요소이름(); // 애너테이션의 요소 선언 ~~~ }
@Override는 애너테이션이고 Override는 애너테이션의 타입이다.
요소
애너테이션 내에 선언된 메서드를 애너테이션의 요소라고 한다.
애너테이션의 요소는 반환값이 있고 매개변수는 없는 추상 메서드의 형태를 가지며, 상속을 통해 구현하지 않아도 된다.
다만, 애너테이션을 적용할 때 이 요소들의 값을 빠짐없이 지정해주어야 한다.요소의 이름도 같이 적어주므로 순서는 상관없다.
예시@interface TestInfo{ int count(); String testedBy(); String[] testTools(); TestType testType(); // enum TestType {FIRST, FINAL} DateTime testDate(); // 자신이 아닌 다른 애너테이션을 포함할 수 있다. }
@interface DateTime{ String yymmdd(); String hhmmss(); }
@TestInfo{ count = 3, testedBy = "Kim" ~~~~ }
애너테이션의 각 요소는 기본값을 가질 수 있으며,
기본값이 있는 요소는 애너테이션을 적용할 때 값을 지정하지 않으면 기본값이 사용된다.
참고 기본값으로 null을 제외한 모든 리터럴이 가능하다@interface TestInfo{ int count() default 1; // 기본값 1 지정 }
애너테이션 요소가 하나이고, 이름이 value인 경우, 적용할 때 요소의 이름을 생략하고 값만 적어도 된다@interface TestInfo{ String value(); } @TestInfo("passed") // @TestInfo(value = "passed")와 같다
마커 애너테이션 Marker Annotation
값을 지정할 필요가 없는 경우, 애너테이션의 요소를 하나도 정의하지 않을 수 있다.
애너테이션 요소의 규칙
요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용된다
()안에 매개변수를 선언할 수 없다.
예외를 선언할 수 없다.
요소를 타입 매개변수로 정의할 수 없다.728x90반응형'Java' 카테고리의 다른 글
Java 람다, 람다식 (3) 2024.02.26 Java 쓰레드(Thread) (1) 2024.02.26 Java 열거형(Enum) (0) 2024.02.26 Java 지네릭스(Generics) (0) 2024.02.26 Java 자료구조, 컬렉션 프레임웍 - 4, (Hash, Set, Map) (2) 2024.02.26