티스토리 뷰
애노테이션
- 프로그램의 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것
- 주석과 마찬가지로 프로그래밍 언어에 영향을 미치지 않으면서도 다른 프로그램에게 유용한 정보 제공
표준 애노테이션
- JDK에서 제공
- 주로 컴파일러를 위한 것
@Override
- 메서드 앞에만 붙일 수 있음
- 조상 클래스의 메소드를 오버라이딩한다는 것을 컴파일러에게 알려줌
- 오버라이딩 할 때 메소드 이름을 잘못 적는 휴먼폴트를 방지할 수 있음
@Deprecated
- 더 이상 사용되지 않는 필드나 메서드에 붙임
- 다른 것으로 대체되었으니 사용하지 않을 것을 권함
- 컴파일시 deprecated된 대상을 사용하고 있다고 에러메시지 띄움
@FunctionalInterface
- 함수형 인터페이스를 올바르게 선언했는지 즉, 추상메서드가 하나뿐인지 확인하고 잘못된 경우 컴파일 에러를 발생시킴
@SuppressWarnings()
- 컴파일러가 보여주는 경고메시지가 나타나지 않게 억제
- “deprecation”
- “unchecked”
- 지네릭스로 타입을 지정하지 않았을 때 발생하는 경고 억제
- “rawtypes”
- 지네릭스를 사용하지 않아서 발생하는 경고 억제
- “varargs”
- 가변인자 타입이 지네릭스 타입일 때 발생하는 경고 억제
@SuppressWarnings("unchecked")
ArrayList list = new ArrayList();
list.add(obj);
@SafeVarargs
- reifiable 타입 : 컴파일 후에도 제거되지 않는 타입
- non-reifiable 타입 : 컴파일 후 제거되는 타입
- 가변 인자의 타입이 non-reifiable 타입일 경우 해당 메서드 선언부와 호출부에서 unchecked 경고가 발생. 이를 억제할 때 @SafeVarargs 를 붙인다.
- static 이나 final이 붙은 메서드, 생성자에서만 사용 가능. 즉, 오버라이드될 수 있는 메서드에서는 사용 불가
class MyArrayList<T> {
T[] arr;
public MyArrayList(T[] arr) {
this.arr = arr;
}
@SafeVarargs //unchecked 경고 억제
@SuppressWarnings("varargs") //varargs 경고 억제
public static <T> MyArrayList<T> asList(T... a) {
return new MyArrayList<>(a);
}
@Override
public String toString() {
return Arrays.toString(arr);
}
}
public class AnnotationEx4 {
public static void main(String[] args) {
MyArrayList<String> list = MyArrayList.asList("1", "2", "3");
System.out.println(list);
}
}
애노테이션 정의하는 방법
@interface 애너테이션이름 {
타입 요소이름();
}
애너테이션의 요소(element) : 애노테이션 내에 선언된 메서드
- 요소 타입으로는 기본형, String, enum, 애노테이션, 클래스만 허용
- 매개변수 선언불가
- 예외 선언불가
- 타입 매개변수로 정의 불가
- 애노테이션을 적용할 때 요소들의 값을 빠짐없이 지정해주어야 함
- 요소의 이름이 value이고 값이 하나뿐일 경우 적용할 때 이름을 생략할 수 있음
모든 애노테이션의 조상은 Annotation (인터페이스) 이다.
- 어노테이션 객체에 대해 equals(), hashCode(), toString() 과 같은 메서드 호출 가능
@Deprecated
@SuppressWarnings("1111")
@TestInfo(testedBy = "aaa", testDate = @DateTime(yymmdd = "220225", hhmmss = "090300"))
public class AnnotationEx5 {
public static void main(String[] args) {
Class<AnnotationEx5> cls = AnnotationEx5.class;
TestInfo anno = cls.getAnnotation(TestInfo.class);
System.out.println("anno.testedBy() = " + anno.testedBy());
System.out.println("anno.testDate().yymmdd() = " + anno.testDate().yymmdd());
for (String str : anno.testTools()) {
System.out.println("testTools = " + str);
}
System.out.println();
Annotation[] annoArr = cls.getAnnotations();
for (Annotation annotation : annoArr) {
System.out.println("annotation = " + annotation);
}
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface TestInfo {
int count() default 1;
String testedBy();
String[] testTools() default "JUnit";
TestType testType() default TestType.FIRST;
DateTime testDate();
}
@Retention(RetentionPolicy.RUNTIME)
@interface DateTime {
String yymmdd();
String hhmmss();
}
enum TestType {FIRST, FINAL}
메타 애노테이션
애노테이션을 정의하는데 사용되는 애노테이션
@retention
- 애노테이션이 유지되는 기간 지정
- SOURCE : 소스 파일에만 존재, 클래스파일(바이트코드)에는 존재하지 않음.
- 컴파일러가 사용하는 애노테이션. e.g. Override, SuppressWarnings
- CLASS : 클래스파일에 존재, 실행시에 사용 불가. 기본값
- 클래스파일이 JVM에 로딩될 때 애너테이션 정보가 무시되어 실행 시 애너테이션에 대한 정보를 얻을 수 없음. 잘 사용되지 않음.
- RUNTIME : 클래스 파일에 존재, 실행시에 사용 가능
- e.g. FunctionalInterface : 컴파일러가 체크하지만, 실행 시에도 사용됨
- 리플렉션이 가능해짐.
- SOURCE : 소스 파일에만 존재, 클래스파일(바이트코드)에는 존재하지 않음.
@target
- 애노테이션이 적용가능한 대상 지정
- ANNOTATION_TYPE
- CONSTRUCTOR
- FIELD : 필드 ( 멤버변수, enum상수). e.g. 기본형 변수
- LOCAL_VARIABLE
- METHOD
- PACKAGE
- PARAMETER
- TYPE : 타입(클래스, 인터페이스, enum)
- TYPE_PARAMETER
- TYPE_USE : TYPE 변수 선언할 때. e.g. 참조형 변수
@Target({FIELD, TYPE, TYPE_USE})
public @interface MyAnnotation {
}
@MyAnnotation //TYPE
class MyClass {
@MyAnnotation //FIELD
int i;
@MyAnnotation //TYPE_USE
MyClass mc;
}
@Documented
- 애너테이션에 대한 정보가 javadoc으로 작성한 문서에 포함되도록 함
@Inherited
- 애너테이션이 자손 클래스에 상속되도록 함
애노테이션 프로세서
- 컴파일 타임에 애노테이션들을 스캐닝하고 프로세싱
- javac에 속한 빌드툴
- 자바코드를 인풋으로 받아서 아웃풋으로 파일(보통 .java)을 생성. 즉, 자바 코드를 생성할 수 있음.
- 단, 이미 존재하는 자바 파일을 수정하는 행위는 불가
- 모든 프로세서는
AbstractProcessor
를 상속 받음- void init(ProcessingEnvironment env)
- boolean boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env)
- 프로세서의 main() 메서드 역할.
- scanning, evaluating, 어노테이션 프로세싱, 자바 파일 생성하는 코드 등 작성
- Set
getSupportedAnnotationTypes() - 어노테이션 프로세서가 처리할 어노테이션 명시
- Full Qualified name을 set에 넣어서 반환
- SourceVersion getSupportedSourceVersion()
- 사용하는 자바버전 명시.
- 보통, SourceVersion.latestSupported() 를 반환
기선님 리뷰 영상
- 애너테이션은 일종의 주석과 같음.
- 동적으로 바뀌는 값(변수)는 애너테이션에 넣을 수 없음.
- e.g. static final(상수) 값만 애너테이션 엘리먼트 값으로 넣을 수 있음
- 에러메시지 안 읽으면 개발자가 아니다.
- source -> class -> runtime
- 리플렉션 (더자바 코드조작 강의)
- JVM 메모리에 있는 정보를 읽어옴
- 클래스명.class.getDeclaredAnnotations() : @Inherited 된 어노테이션을 제외하고, 자식 클래스에 선언되어 있는 annotation 들을 얻어올 수 있음. (private 으로 선언되어 있는 것도 가져올 수 있음)
Retention
- 커스텀한 어노테이션을 만든다면 Retention을 무엇으로 설정할지 고민해보아라.
- 리플렉션까지 사용을 안할 것 같아. -> CLASS로 내려감
- 소스코드에서만 쓸 것 같아. -> SOURCE로 한 단계 더 내려감
- 커스텀한 어노테이션을 만든다면 Retention을 무엇으로 설정할지 고민해보아라.
javadoc 활용 끝판왕 : mockito
ServiceLoader
- Interface 만 알고 있는 상태에서 구현체를 사용할 수 있음. 즉, 구현체가 뭔지 모르는 상태에서 구현체를 사용할 수 있음.
- 구현체 jar 파일을 생성하기 전에,
- resources/META-INF/services 하위에 인터페이스의 Fully Qulified Name 으로 파일을 하나 생성
- 해당 파일 내에 구현체의 FQN을 명시.
- 구현체 Jar 파일을 만들고 나면, 이 Jar 파일을 사용하는 프로젝트에서는 구현체 정보를 모르고, 인터페이스 정보만 아는 상태에서 구현체를 사용할 수 있게 됨.
개발자의 중요한 소양. 얼마나 빠르게 학습할 수 있는가.
- 이를 위해서는 베이스를 쌓아 가야 함. 무엇이든 공부를 계속 해나가는 것이 중요.
리플렉션과 어노테이션 프로세싱을 구분하자
- 어노테이션 프로세싱 : 어노테이션 프로세서를 따로 구현을 해놓은 것.
References
'JAVA' 카테고리의 다른 글
[자바 스터디] 12주차 : 제네릭 (0) | 2022.03.20 |
---|---|
[자바 스터디] 11주차 : I/O (0) | 2022.03.06 |
[자바 스터디] 10주차(1) : Enum (0) | 2022.02.26 |
[자바 스터디] 9주차 : 멀티쓰레드 프로그래밍 (0) | 2022.02.20 |
[자바 스터디] 8주차 : 예외 처리 (0) | 2022.02.11 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 코테
- 프록시
- 토비의봄TV
- 토비의스프링
- 백기선
- 디자인패턴
- 객체지향
- 데코레이터패턴
- provider
- 자바
- 자바스터디
- c++
- gracefulshutdown
- 메서드레퍼런스
- 프로그래머스
- 김영한
- OOP
- 코딩테스트
- 스프링
- BOJ
- SOLID
- ec2
- 템플릿콜백
- java
- 서비스추상화
- 프록시패턴
- 예외처리
- AOP
- 카카오
- 토비
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함