애너테이션
우리는 코딩 할 때 모든걸 손으로 치긴해도, 모든걸 기억할 순 없다.
그래서 주석으로 이 코드가 뭘 하는지 뭘 의미하는지 적어놓는데, 애너테이션도 비슷한 맥락이다.
애너테이션은 정보를 전달하고자 하는 대상이 사람이 아닌 다른프로그램(콤퓨타)인 것에 차이가 있다.
애너테이션의 대표적인 역할은
- 컴파일러에게 문법체크를 하도록 정보제공
- 프로그램을 빌드 시 코드를 자동으로 생성하기 위한 정보 제공
- 런타임(실행 중에) 특정 기능을 실행하도록 정보 제공
예를들어, 애너테이션은 PC에게 "빌드할 때 이거 한번 문제있는지 봐라!" 라고 말해주는 것과 비슷하다.
꼭 빌드가 아니여도 뭐 좀 유심히 봐달라 라고 말해주는 것과 같다.
애너테이션의 종류
에너테이션에는 크게 3가지 종류가 있는데, 그 중에서 우리는 주로 2가지 (표준 애너테이션, 메타 애너테이션)을 사용한다.
- 표준 애너테이션: 자바에서 기본적으로 제공하는 애너테이션
@Override | 컴파일러에게 메서드를 오버라이딩하는 것이라고 알림 |
@Deprecated | 앞으로 사용하지 않을 대상을 알릴 때 사용 |
@FunctionalInterface | 함수형 인터페이스라는 것을 알 |
@SuppressWarning | 컴파일러가 경고메세지를 나타내지 않음 |
- 메타 애너테이션: 애너테이션에 붙이는 애너테이션으로, 애너테이션을 정의하는 데에 사용
@Target | 애너테이션을 정의할 때 적용 대상을 지정하는데 사용한다. |
@Documented | 애너테이션 정보를 javadoc으로 작성된 문서에 포함시킨다. |
@Inherited | 애너테이션이 하위 클래스에 상속되도록 한다. |
@Retention | 애너테이션이 유지되는 기간을 정하는데 사용한다. |
@Repeatable | 애너테이션을 반복해서 적용할 수 있게 한다. |
위의 두개가 주로 사용도는 애너테이션이고, 나머지 하나는 사용자 애너테이션으로, 사용자가 직접 정의하여 사용한다.
표준 애너테이션
표준 에너테이션은 자바가 기본적으로 제공하는 에너테이션이다.
대표적으로 많이 사용되는것 몇가지만 살펴보자
@Override
@Override는 메서드 앞에만 붙일 수 있는 애너테이션으로 선언한 메서드가 상위 클래스의 메서드를 오버라이딩 하는 메서드라는 것을 컴파일러에게 알려주는 역할을 한다.
종종 오버라이딩 할 때 오타 등의 이유로 메서드의 이름을 잘못 작성하는 경우가 있다.
class Super {
void run() {}
}
class Sub extends Super {
void rnu() {} // 오버라이딩을 하려고 했으나 오타가 발생함.
}
run()메서드를 rnu으로 오타 낸 상황.
이때는 서로 이름이 다르니 오버라이딩이 아니고, 그냥 새로운 메서드가 생겻나보다 하고 말아버린다.
이를 방지하기 위해 @Override를 사용하는 것이다.
class Super {
void run() {}
}
class Sub extends Super {
@Override
void rnu() {} // 컴파일 에러 발생, 오타가 난 것을 발견할 수 있음.
}
위의 코드를 보면, @Override 가 밑의 rnu 메서드가 오타난 것을 감지하기 위해 넣은것을 볼 수 있다.
@Override 는 해당 메서드(rnu으로 잘못 친 run)가 상위클래스(Super)의 메서드(run)을 오버라이딩 한 메서드 이며, 오버라이딩이 잘 된건지, 안된건지 검사해달라고 요청하는 애너태이션 인 것이다.
(이 상황에서는 오타 + 오버라이딩 한것이라고 알려준 것이니 컴파일러가 "님 실수함 ㅎ!" 하고 컴파일 에러를 알려준다. )
@Deprecated
@Deprecated는 모종의 이유로 더이상 사용되지 않는 필드, 메서드가 있는 경우에 사용한다.
이 애너테이션을 붙이면, "이거는 더이상 사용하지 않으니 주의해라" 라고 말해주는 것이다.
코드 예시
class OldClass {
@Deprecated
int oldField;
@Deprecated
int getOldField() { return oldField; };
}
위의 코드를 보면 oldField 변수와 getOldField()메서드가 이제는 사용되지 않는다고 말해주는 것이다.
"왜 굳이 이렇게 남겨놓나? 그냥 삭제하면 되는데"
구버젼으로도 돌아갈 수 있게 하려고 이전에 되던것들을 남겨둘 때 사용될 수 있는 것이다.
@SuppressWarnings
@SuppressWarnings는 컴파일 경고 메시지가 나타나지 않도록 하는 애너테이션이다.
영화에서 보면 우주선 경보가 나올 때 시끄럽다고 경보를 끈다. 딱 이 기능이다.
@SuppressWarings(”all”) | 모든 경고를 억제 |
@SuppressWarings(”deprecation”) | Deprecated 메서드를 사용한 경우 나오는 경고 억제 |
@SuppressWarings(”fallthrough”) | switch문에서 break 구문이 없을 때 경고 억제 |
@SuppressWarings(”finally”) | finally 관련 경고 억제 |
@SuppressWarings(”null”) | null 관련 경고 억제 |
@SuppressWarings(”unchecked”) | 검증되지 않은 연산자 관련 경고 억제 |
@SuppressWarings(”unused”) | 사용하지 않는 코드 관련 경고 억제 |
만약 위의 경고 억제 중에 몇개만 채택하고 싶으면 (한번에 여러개를 억제하고 싶으면)
@SuppressWarnings({"deprecation", "unused", "null"})
이르케 한번에 선언도 가능하다.
@FunctionalInterface
@FunctionalInterface은 함수형 인터페이스를 선언할 때 컴파일러가 함수형 인터페이스가 바르게 선언되었는지 확인하는 것이다.
코드 예시
@FunctionalInterface
public interface Runnable {
public abstract void run (); // 하나의 추상 메서드
}
(함수형 인터페이스는 단 하나의 추상 메서드만 가져야 하는 제약이 있다.)
@FunctionalInterface없이도 함수형 인터페이스를 선언 가능 하지만, 실수방지용으로 넣어두는 것이다.
메타 애너테이션
우리가 이전에 메타인지가 생각을 위한 생각 이라고 했듯이, 메타 애너테이션은 애너테이션을 위한 애너테이션이다.
대표적인것 일부만 보자.
@Target
@Target은 애너테이션을 적용할 대상을 지정할 때 사용한다.
코드 예시
import static java.lang.annotation.ElementType.*;
//import문을 이용하여 ElementType.TYPE 대신 TYPE과 같이 간단히 작성할 수 있습니다.
@Target({FIELD, TYPE, TYPE_USE}) // 적용대상이 FIELD, TYPE
public @interface CustomAnnotation { } // CustomAnnotation을 정의
@CustomAnnotation // 적용대상이 TYPE인 경우
class Main {
@CustomAnnotation // 적용대상이 FIELD인 경우
int i;
}
위의 코드에서 @Target뒤에 필드, 타입 등을 지정 한 것을볼 수 있다.
지정할 수 있는 타입은 아래와 같다.
ANNOTATION_TYPE | 애너테이션 |
CONSTRUCTOR | 생성자 |
FIELD | 필드(멤버변수, 열거형 상수) |
LOCAL_VARIABLE | 지역변수 |
METHOD | 메서드 |
PACKAGE | 패키지 |
PARAMETER | 매개변수 |
TYPE | 타입(클래스, 인터페이스, 열거형) |
TYPE_PARAMETER | 타입 매개변수 |
TYPE_USE | 타입이 사용되는 모든 대상 |
@Documented
@Documented은 애너테이션에 대한 정보가 javadoc으로 작성한 문서에 포함되도록 하는 설정이다.
표준, 메타 애너테이션 중 @Override와 @SuppressWarnings를 제외하고 모두 @Documented가 적용 되어 있다.
코드 예시
@Documented
@Target(ElementType.Type)
public @interface CustomAnnotation { }
@Inherited
@Inherited는 하위 클래스가 애너테이션을 상속받도록 하는 애너테이션이다.
해당 애너테이션을 상위클래스에 붙이면 하위 클래스도 상위 클래스에 붙은 애너테이션들이 동일하게 적용된다.
코드 예시
@Inherited // @SuperAnnotation이 하위 클래스까지 적용
@interface SuperAnnotation{ }
@SuperAnnotation
class Super { }
class Sub extends Super{ } // Sub에 애너테이션이 붙은 것으로 인식
위의 코드에서 Super를 상속받은 Sub에서도 @SuperAnnotation에 정의된 내용들을 적용 받는다.
사용자 정의 애너테이션
사용자가 직접 정의하는 애너테이션이다.
인터페이스를 정의하는것과 비슷하다.
@interface 애너테이션명 { // 인터페이스 앞에 @기호만 붙이면 애너테이션을 정의할 수 있습니다.
타입 요소명(); // 애너테이션 요소를 선언
}
사용자 정의 애너테이션은 다른 클래스나 인터페이스를 상속 받을 수 없다.
'백엔드 > JAVA_이론공부' 카테고리의 다른 글
JAVA_스트림, 파일입출력 (0) | 2022.09.28 |
---|---|
JAVA_람다(람다식) (0) | 2022.09.28 |
JAVA_제네릭 (0) | 2022.09.28 |
JAVA_열거형 (0) | 2022.09.28 |
JAVA_인터페이스 (0) | 2022.09.22 |