▩ 목 차 ▩
1. 어노테이션이란 ?
1-1. 미리 정해져 있는 어노테이션들은 딱 3개뿐
1-1-1. @Override
1-1-2. @Deprecated
1-1-3. SupressWarings
1-2. 어노테이션을 선언하기 위한 메타 어노테이션
1-2-1. @Target
1-2-2. @Retention
1-2-3. @Documeted
1-2-4. @Inherited
1-3. 어노테이션을 선언해보자
1-4. 어노테이션에 선언한 값은 어떻게 확인할까?
1-5. 어노테이션도 상속이 안돼요.
1-6. 어노테이션의 용도에 따라서 다음과 같이 나눌 수 있다.
2. 정리
■ 1. 어노테이션이란 ? ■
어노테이션은 클래스나 메소드 등의 선언시에 @를 사용하는 것을 말한다.
어노테이션은 영어로 Annotation이며, 메타데이터라고도 불리기도 한다.
어노테이션은, 아래의 경우에 사용한다.
- 컴파일러에게 정보를 알려주거나
- 컴파일할 때와 설치시의 작업을 지정하거나
- 실행할 때 별도의 처리가 필요할 때
어노테이션은 클래스, 메소드, 변수 등 모든 요소에 선언 할 수 있다.
어토테이션이 프로그램에 영향을 미칠까?
==> 영향이 있는 어노테이션도 있고 그렇지 않은 것도 있다.
■ 1-1. 미리 정해져 있는 어노테이션들은 딱 3개뿐
자바 언어에는 사용하기 위해서 정해져 있는 어노테이션은 3개가 있고, 어노테이션을 선언하기 위한 메타 어노테이션이라는 것은 4개가 있다.
여기서 메타 어노테이션은 선언을 위해 존재하기 떄문에 일반적으로 사용 가능한 어노테이션은 다음의 3개 뿐이다.
- @Override
- @Deprecated
- @SupressWarinigs
■ 1-1-1. @Override
해당 메소드가 부모 클래스에 있는 메소드를 Override 했다는 것을 명시적으로 선언한다.
[ Override를 할 때에는 부모 클래스에 있는 메소드의 이름과 매개변수들을 동일하게 가져간다.]
쉽게 말로 풀어 설명한다면,
만약 자식 클래스에 여러 개의 메소드가 있을 때, 어떤 메소드가 Override 되었는지 쉽게 알 수 없을 수도 있고, 제대로 메소드를 Override 했다고 생각했는데, 매개 변수가 하나 빠졌을 수도 있다. 따라서, 명확하게 "이 메소드는 Override 된 거 니까 잘못 코딩했으면 컴파일러 너가 알려줘" 라고 지정해주는것이라고 생각하면 편하다.
■ 1-1-2. @Deprecated
미리 만들어져 있는 클래스나 메소드가 더 이상 사용되지 않은 경우 Deprecated 되었다고 한다.
쉽게 말로 풀어 설명한다면,
컴파일러에게 "얘는 더 이상 사용하지 않으니까 그렇게 알고, 나중에 이것을 쓰면 경고 한번 해줘"라는 것이라고 생각하면 편하다.
그냥 지워버려도 되는데 애 Deprecated라고 표시를 해야할까?
==> 만약 다른 사람들과 같이 개발을 하고 있는데 어떤 클래스나 메소드가 불필요하다고 생각해서 지워버리면 이 지워버린 메소드를 참조하는 다른 개발자가 만든 프로그램이 변경된 사항을 모르고 있다면, 컴파일 할 때 에러가 발생할 것이다. 그러므로 하위 호환성을 위해서 Deprecated로 선언하는 것은 꼭 필요하다. [ 가장 좋은 방법은 일정 기간을 거쳐 알림을 준 후에 지우는 것이 바람직 하다. ]
■ 1-1-3. SupressWarings
쉽게 말로 풀어 설명한다면,
코딩을 하다 보면 컴파일러에서 경고를 알리는 경우가 있다. 프로그램에는 문제가 없는데, 내가 잘 알아서 하는데 이러한 경고가 나타나면 웬지 마음이 불편하기도 하다. 그럴때 컴파일러에게 "얘는 내가 일부러 이렇게 코딩한 거니까 경고를 해줄 필요 없어"라고 생각하면 편하다.
이것은 사용하는 방법은 다른 어노테이션들과 다르게 @SupressWarings + 소괄호 속에 문자열을 넘겨 준다. [ 그냥 소괄호를 사용하지 않고 단순히 @SupressWarings를 사용해도 문제는 없다. ]
[EX] : @SupressWarings("하고 싶은 말")
이 SupressWarings를 너무 남용할 경우 Deprecated된 메소드를 사용해도 모르고 넘어갈 수도 있으니 유의해야한다.
■ 1-2. 어노테이션을 선언하기 위한 메타 어노테이션
메타 어노테이션이라는 것은 어노테이션을 우리가 선언할 때 사용한다.
[대부분의 개발자들은 어노테이션을 선언할 일이 별로 없다. 이미 선언되어 있는 어노테이션을 사용하기에도 벅찬 것이 현실이기 때문이다.]
- @Target
- @Retention
- @Documented
- @Inherited
[ 어노테이션을 선언할 때 꼭 이 4개를 모두 사용해야 하는것은 아니지만, 4개가 있다는 것은 알아두면 좋다. ]
추가로 알아야 할 것은 @interface다. 이 어노테이션은 어노테이션을 선언할 때 사용한다.
■ 1-2-1. @Target
어노테이션을 어떤것에 적용할지를 선언할 때 사용한다. 적용 방법은 다음과 같다.
@Target(ElementType.METHOD)
@Target() 괄호 안에 적용 대상을 지정하는데, 그 대상 목록은 아래와 같다.
■ 1-2-2. @Retention
얼마나 오래 어노테이션 정보가 유지되는지를 다음과 같이 선언한다.
@Retention(RetentionPolicy.RUNTIME)
@Target 처럼 괄호 안에 지정하는 적용 가능한 대상은 아래와 같다.
■ 1-2-3. @Documeted
해당 "어노테이션에 대한 정보가 Javadocs(API)문서에 포함된다는 것"을 선언한다.
■ 1-2-4. @Inherited
모든 자식 클래스에서 부모 클래스의 어노테이션을 사용 가능하다는 것을 선언한다.
■ 1-3. 어노테이션을 선언해보자
[ 어노테이션 관련 클래스들은 java.lang.annotation 패키지에 선언되어 있다. ]
[EX] - 어노테이션 선언
package part17;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD) // 1
@Retention(RetentionPolicy.RUNTIME) // 2
public @interface UserAnnotation { // 3
public int number(); // 4
public String text() default "This is first annotation"; // 5
}
위의 코드에서 주석에 적힌 번호대로 설명을 하겠다.
- @Traget은 해당 어노테이션 사용 대상을 지정한다. 여기서는 ElementType.METHOD를 소괄호 안에 넣어 줌으로써 이 어노테이션은 메소드에 사용할 수 있다고 지정된 것이다.
- @Retention은 어노테이션 유지 정보를 지정하는데 사용한다. 소괄호 안에 RetentionPolicy.Runtime으로 지정하면 실행시에 이 어노테이션을 참조하게 된다.
- 어노테이션 이름인 UserAnnotation 앞에 @interface가 선언되어 있다. 처음 보면 익숙하지 않겠지만, 클래스나 인터페이스를 서언할 때 처럼 @interface로 선언하면 @userAnnotation으로 어노테이션이 사용 가능해진다.
- 어노테이션 선언 안에는 number()라는 메소드와 text()라는 메소드가 있다. number()의 리턴 타입은 int이며, text()의 리턴 타입은 String이다 이렇게 메소드처럼 어노테이션 안에 선언해놓으면, 이 어노테이션을 사용할 때 해당 항목에 대한 타입으로 값을 지정 가능하다.
- text()를 보면, default라는 예약어를 쓴 뒤 문자열이 지정되어 있는 것을 볼 수 있다. default 예약어를 사용할 경우에는, default 뒤에 있는 값이 이 어노테이션을 사용할 때의 기본값이 된다. 즉, 값을 지정하지 않아도 default 값으로 지정된다.
[EX] - 어노테이션 선언한 것을 사용
package part17;
public class UserAnnotationSample {
@UserAnnotation(number=0)
public static void main(String[] args) {
UserAnnotationSample sample = new UserAnnotationSample();
}
@UserAnnotation(number=1)
public void annotationSample1() {
// TODO Auto-generated method stub
}
@UserAnnotation(number = 2, text="second")
public void annotationSample2() {
}
@UserAnnotation(number = 3, text="third")
public void annotationSample3() {
}
}
어노테이션 선언 클래스에 지정해 놓은 각 메소드의 이름에 해당하는 값을 소괄호 안에 넣어 주어야만 한다.
즉, number()와 text()에 해당하는 어노테이션 값을 지정해 주면 된다. 추가로 text()의 경우 default를 사용하여 기본 값을 지정해 주었기 때문에 별도로 값을 지정해 주지 않아도 컴파일 하는 데 전혀 문제가 없지만, number()는 기본값이 지정되어 있지 않으므로 반드시 값을 정해주어야만 한다.
UserAnnotation은 대상이 메소드뿐인데, 만약 생성자나 클래스에서도 사용할 수 있도록 하려면 하면 아래와 같이 @Target 부분을 수정하자.
@Target({ElementType.METHOD,ElementType.TYPE})
■ 1-4. 어노테이션에 선언한 값은 어떻게 확인할까?
구현한 어노테이션 값을 어떻게 확인할 수 있을까? 일반적으로는 우리가 어노테이션을 만들 일은 거의 없다.
따라서, 어노테이션에서 선언한 값을 확인하느 코드를 만들일도 거의 없을 것이다. 그냥 한번만 확인 해보자.
[EX] - 어노테이션에 선언한 값 확인
package part17;
import java.lang.reflect.Method;
public class UserAnnotationCheck {
public static void main(String[] args) {
UserAnnotationCheck sample = new UserAnnotationCheck();
sample.checkAnnotations(UserAnnotation.class);
}
public void checkAnnotations(Class useClass) {
Method[] methods= useClass.getDeclaredMethods();
for(Method tempMethod:methods) {
UserAnnotation annotation =
tempMethod.getAnnotation(UserAnnotation.class); //2
if(annotation!=null) {
int number = annotation.number(); //3
String text = annotation.text();
System.out.println(tempMethod.getName());
}
else {
System.out.println(tempMethod.getName()
+"() : annotations is null.");
}
}
}
}
number() : annotations is null.
text() : annotations is null.
위의 코드는 지금까지 봐온 코드들 중 가장 어려울 것이다. 여기서 Class, Method라는 것은 자바의 리플렉션 이라는 API에서 제공하는 클래스들이다. class 라는 클래스는 클래스의 정보를 확인하고, Metod라는 클래스는 메소드의 정보를 확인하는데 사용한다.
위의 코드에서 숫자 주석들을 확인해보자.
- Class 클래스에 선언되어 있는 getDeclareMethods() 메소드를 호출하면, 해당 클래스에 선언되어 있는 메소드들의 목록을 배열로 리턴한다.
- Method 클래스에 선언되어 있는 getAnnotation()이라는 메소드를 호출하면, 해당 메소드에 선언되어 있는 매개 변수로 넘겨준 어노테이션이 있는지 확인하고, 있을 경우 그 어노테이션의 객체를 리턴해준다.
- 어노테이션에 선언된 메소드를 호출하면, 그 값을 리턴해준다.
위의 코드의 결과값은 어노테이션이 없기 때문에 null 값이 나왔다.
■ 1-5. 어노테이션도 상속이 안돼요.
자바의 상속은 많은 이점을 제공한다.
enum 클래스가 상속을 지원하지 않듯이, 어노테이션을 선언할 때에도 미리 만들어 놓은 어노테이션을 확장하는 것이 불가능하다.
즉, extends 예약어를 사용할 수 없다.
■ 1-6. 어노테이션의 용도에 따라서 다음과 같이 나눌 수 있다.
- 제약사항 등을 선언하기 위해 : @Deprecatd, @Override, @NotNull
- 용도를 나타내기 위해 : @Entity, @TestCase, @WebService
- 행위를 나타내기 위해 : @Satatefull, @Transaction
- 처리를 나타내기 위해 : @Column, @XmlElement
■ 2. 정리 ■
우리가 어노테이션을 직접 선언하여 개발할 일은 거의 없다. [ 거의 5년간 ]
하지만, 이미 만들어져 있는 어노테이션을 사용하는 방법은 알고 있어야만 한다.
다른 내용들은 다 잊어버려도 되늗네 @Override, @SuppressWarinigs, @Deprecated 어노테이션은 꼭 기억해두자.
최근에 만들어진 많은 자바 기반의 프레임웍들은 어노테이셔을 사용하여 코듸 양을 매우 많이 줄이고, 단순 반복적인 작업도 줄이는데 도움을 준다. 하지만 단순하게 어노테이션을 사용하는 방법을 알면 실력이 늘지 않는다. 어노테이션을 지정하면 코드가 내부적으로 어떻게 변환되는지에 대해서 살펴보는 습관을 가져보면 좋다.
'JAVA > 자바의신 1' 카테고리의 다른 글
18장 기본 문법은 거의 다 배웠으니 정리해보자 (0) | 2022.09.13 |
---|---|
16장 클래스 안에 클래스가 들어갈 수도 있구나 (0) | 2022.09.12 |
15장 String (0) | 2022.09.10 |
14장 다 배운 것 같지만, 예외라는 중요한 것이 있어요.(예외 처리 try-catch) (1) | 2022.09.09 |
13장 인터페이스와 추상클래스, enum (0) | 2022.09.09 |