[JAVA] 애너테이션 ( Annotation ) ①

DongGyu Jung·2022년 3월 24일
0

자바(JAVA)

목록 보기
42/60
post-thumbnail

🏃‍♂️ 들어가기 앞서..

본 게시물은 스터디 활동 중에 작성한 게시물로 자바의 정석-기초편 교재를 학습하여 정리하는 글입니다.
※ 스터디 Page : 〔투 비 마스터 : 자바〕

*해당 교재의 목차 순서와 구성을 참고하여 작성하며
각 내용마다 부족할 수 있는 내용이나 개인적으로 궁금한 점은
추가적인 검색을 통해 채워나갈 예정입니다.



📌 애너테이션 ( annotation )

말 그대로 " 주석 "처럼 프로그래밍 언어에 영향을 미치지 않으며 유용한 정보를 제공 하는 것
( " /** "로 시작하는 주석 → 소스코드 설명 & 미리 정의된 @ 붙은 태그를 활용해 주석 안에 정보 저장
javadoc.exe 프로그램을 통해 문서 작성 )

따로 문서를 작성하고 소스코드가 변경될 때마다 문서도 업데이트 해야했었던 과거와 다르게
한 번에 " 소스코드의 주석 "으로부터 HTML 문서를 생성해 낸다. (javadoc.exe)

아마 자바 코드들을 지금까지 봐오면서
많이 봤을 것이다.
특히, 재선언하는 Override가 대표적인 애너테이션에 사용되는 요소인데
@Override 라고 Override하는 메서드들 위에 주석같이 달려있는 것을 많이 봤을 것이다.

그것이 바로 애너테이션(annotation) 이다.

" 이 메서드는 Override 하는 것이다. " 라는 것을
일일이 프로그램에게 알려줄 필요없이
@Override태그로 간단히 붙이면 끝이고

심지어
" 프로그램 컴파일러 "에게 알리는 역할까지 하면서도
메서드가 포함된 프로그램 자체에는 아무 영향을 끼치지 않는다.
( 단, 해당 프로그램에서 미리 정의된 종류와 형식으로 작성해야 의미가 있다. )


※ 표준 애너테이션

자바에서 기본적으로 제공하는 애너테이션

애너테이션설명
@Override해당 메서드를 오버라이딩 하는 것이다.
@Deprecated앞으로 사용하지 않을 것을 권장한다.
@SuppressWarnings컴파일러 특정 경고메세지 차단
@SafeVarargs지네릭스 타입의 가변인자 사용
@FunctionalInterface함수형 인터페이스이다.
@Nativenative메서드에서 참조되는 상수 앞에 붙인다.
[[ 애너테이션을 만들 때 사용 ]]
@Taget*애너테이션 적용 가능 대상 지정
@Documented*해당 애너테이션 정보가 javadoc 작성 문자에 포함되게끔
@Inherited*" 자손 클래스 "에상속되도록
@Retention*애너테이션 유지 범위 지정
@Repeatable*애너테이션 반복 적용 허용

-Xlint 사용하기

1. 코드 작업 중인 해당 java파일이 위치한 디렉토리의 주소 복사

2. cmd 창 ▶ 해당 디렉토리로 이동

3. javac 자바파일명.java 컴파일

+ javac -Xlint 자바파일명.java 실행하면 더 자세한 내용 확인 가능


@Override

  • 메서드 앞에만 붙일 수 있는 애너테이션
  • ' 이름 실수 ' or ' 오버라이딩할 때 자주 발생하는 실수 '들에 대해
    컴파일러가 이를 알아들을 수 있도록
// 상속받을 부모 메서드
class Parent {
	void parentMethod() { }
}
 
class Child extends Parent {
	void parentmethod() {} // 이름 틀리게 작성
}

/*
이럴 경우에
컴파일러는 그저 "새로운 이름의 메서드가 추가된 것" 이라고 인식을 하게되서
오류메세지도 발생하지 않고 그냥 넘어가게됨.
*/
class Child extends Parent {
	@Override
	void parentmethod() {} // 에러 메세지가 발생
}

/*
error : method
does not override or implement a method from a supertype
@Override
^
1 error

라고 본래 목적이였던 "오버라이딩"에 대한 실수라고 컴파일러가 인식할 수 있게 된다.
*/

@Deprecated

새로운 버전으로 JDK가 업데이트 될 때, 새로운 기능 추가 및 기존 기능 개선 등이 되었다고
이미 사용되고 있는 것들을 삭제할 수 없기 때문에
앞으로 사용하지 않는 것이 좋을 것들에 해당 애너테이션을 붙인다.

  • 앞으로 사용하지 않을 것을 권장하는 필드/메서드에 붙이는 애너테이션
    붙게 되면 이전에 사용했던 코드를 실행했을 때 권고 메세지 출력
    ( 사용이 아예 불가능하게 되는 것은 아님!! )
    ex. java.util.Date클래스 → Java API 에 Deprecated. 라고 작성되어 있다.
// 실제 Date클래스의 getDate 메서드 코드
@Deprecated
public int getDate() {
	return normalize().getDayOfMonth();
}
  • @Deprecated가 붙은 대상을 사용하게 되면 에러가 아닌 Note메세지가 나타난다.
Note : Annotation자바파일명 uses or overrides a deprecated API.
Note : Recompile with -Xlint:deprecation for details.

@FunctionalInterface

Override 애너테이션과 유사하게
" 함수형 인터페이스 "를 선언할 때, @FunctionalInterface를 붙이면
올바르게 선언했는지 확인하고
잘못되었을 때 에러를 발생 시킨다.
( 함수형 인터페이스는 추상메서드가 하나뿐이어야 한다는 제약 )

// 안붙여도 되지만 붙이면 컴파일러의 올바른 작동을 제고시킬 수 있음 
@FunctionalInterface
public interface Runaable {
	public abstract void run(); // 추상 메서드
}

@SuppressWarnings

  • 경고메세지 억제 기능
    → 괄호 안에 억제할 경고 종류 " 문자열 "로 지정
/* 잘못됨 */
ArrayList list = new ArrayList();
list.add(obj) 
// obj타입을 ArrayList 객체에 add 할때 지네릭 타입을 지정하지 않으면 
//지네릭 타입 미지정 unchecked 경고 발생


/* 올바름/애너테이션 활용 */
ArrayList list = new ArrayList<T>();
list.add(obj) ;

@SuppressWarnings("unchecked")
ArrayList list = new ArrayList();
list.add(obj) // 지네릭 타입 미지정 unchecked 경고 발생 억제
  • 둘 이상의 경고 동시 억제 : 중괄호안에 경고 종류 입력
@SuppressWarnings({"unchecked", "deprecation", "varargs"})

"deprecation" : @Deprecated붙은 대상을 사용했을 때 경고 발생

"unchecked" : 지네릭스로 타입을 지정하지 않았을 때 경고 발생

"varargs" : 가변인자 타입이 지네릭 타입일 때 경고 발생

"rawtypes" : 지네릭스를 사용하지 않아서 경고 발생



🔨 메타 애너테이션

""" 애너테이션을 위한 애너테이션 """
: 애너테이션을 만들 때 사용
(java.lan.annotation패키지에 포함)

@Target

  • 애너테이션 적용 대상 지정
대상 타입설명
ANNOTAION_TYPE애너테이션
CONSTRUCTOR생성자
FIELD필드 ( iv_인스턴스변수 / enum 상수 )
LOCAL_VARIABLE지역변수
METHOD메서드
PACKAGE패키지
PARAMETER매개변수
TYPE타입 ( class, interface, enum )
JDK1.8 ~
TYPE_PARAMETER타입 매개변수
TYPE_USE타입이 사용되는 모든 곳

앞서 알아봤던 SuppressWarnings 애너테이션의 경우를 살펴보면

/*
SuppressWarnings 애너테이션 ( @SuppressWarnings )이 적용될 수 있는 대상을 지정해줌
*/

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
// 클래스,인터페이스,enum, 멤버변수, enum 상수, 매개변수, 메서드, 생성자, 지역변수에 적용할 수 있게끔
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
	String[] value() ;
}

@Retention

  • 애너테이션 유지 기간 설정
    @Retention( RetentionPolicy.유지기준)
유지 기준의미
SOURCE" 소스파일에만 존재 "_ 클래스 파일에 X
( 애너테이션 정보가 클래스 파일에 남아있지 않음. )
CLASS [기본값]" 클래스 파일에 존재 " → 실행시 사용 불가
RUNTIME" 클래스 파일에 존재 " → 실행시 사용 가능

Override 애너테이션의 경우를 살펴보면 이러하다.

/*
Override 애너테이션 : Override 체킹만 해주고 클래스 파일엔 저장되지 않는 애너테이션
*/
@Target( ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {}

반면 FunctionalInterface 애너테이션은 클래스 파일에까지 저장되는
RUNTIME 기준을 사용한다.

/*
FunctionalInterface 애너테이션
*/
@Documented
@Target( ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface FunctionalInterface {}

@Documented / @Inherited

  • @Documented = javadoc으로 작성한 문서에 " 포함시키려면 "
    ( @Override@FunctionalInterface를 제외하고 모두 붙어있음 )

  • @Inherited = 자손 클래스에까지 같이 상속되게끔

@Inherited
@interface MyAnno{}

@MyAnno
class Parent{}

class Child extends Parent{} // Parent클래스에 붙어있던 MyAnno가 동일하게 붙어있는 효력

@Repeatable

  • 반복해서 붙일 수 있는 애너테이션에 사용

한 클래스에 @Repeatable이 붙은 애너테이션을 여러개 중복해서 붙일 수 있다.

단, 같은 이름의 애너테이션이 중복해서 달려있는 것이 가능하기 때문에
하나로 묶어서 다룰 수 있는 애너테이션도 같이 정의해주어야한다.
( 배열타입의 요소의 이름 = " 반드시 value " )

/* 여러개의 애너테이션을 담을 "컨테이너 애너테이션" */
@interface ToDos {
	ToDo[] value(); // 반드시 value
}
/* Repeatable 한 애너테이션 */
@Repeatable(ToDos.class) // 컨테이너 애너테이션 지정해줘야 함.
@interface ToDo {
	String value();
}


@ToDo("update codes")
@ToDo("override inherited methods")
// 더 추가할 수 있음.
class MyClass {
	...
}

0개의 댓글