JAVA 스프링을 보면서 어노테이션을 굉장히 많이 활용하는 것을 보고 조사해야 겠단 생각이 들어서 조사를 했습니다.
1. 어노테이션이란?
어노티에션은 메타데이터로 클래스 파일에 임베디드되어 컴파일러에 의해 생성된 후 자바 가상머신에 포함되어 작동됩니다.
즉, 어노테이션이 있으면 프로그래머 입장에서 해당 코드가 어떤 상태인지 알 수 있는 가독성이 올라가게 되며,
컴퓨터 입장에서는 해당 코드에 오류발생시 좀 더 정확한 지점의 오류를 찾아줄 수 있는 좋은 메타데이터 입니다.
여기서 메타데이터란 데이터에 대한 데이터라는 뜻으로 데이터가 데이터의 상태를 표현한다. 라고 생각해주시면 될 것 같습니다.
2. 어노테이션의 종류
어노테이션에는 기본 어노테이션, JAVA 커스텀 어노테이션이 있습니다.
우선 기본 어노테이션부터 살펴보자면 다음과 같습니다.
기본 어노테이션
- @Override
메소드가 오버라이드 됐는지 검증합니다.
만약 부모클래스로 부터 상속을 받고 자식 클래스에서 부모 함수를 오버라이드 할 때, 오버라이드가 잘 되지 않으면 에러메시지를 띄워줍니다.
class Animal{
void eatSomething(){System.out.println("eating something");}
}
class Dog extends Animal{
@Override
void eatsomething(){System.out.println("eating foods");}//should be eatSomething
}
class TestAnnotation1{
public static void main(String args[]){
Animal a=new Dog();
a.eatSomething();
}
}
output :
Compile by: javac TestAnnotation1.java
tAnnotation1.java:13: error: cannot find symbol
a.eatsomething();
^
symbol: method eatsomething()
location: variable a of type Animal
1 error
해당 코드는 부모클래스의 함수 eatSomething와 자식 클래스 함수 eatsomething를 보시면 됩니다.
(중간에 s가 대문자와 소문자로 다릅니다.)
위에 @Override가 없을 시 실행하면 부모 클래스의 함수가 실행되지만,
@Override를 작성시 에러 메시지를 띄워줍니다.
- @SupperssWarnings
이건 컴파일 경고를 무시해주는 명령어입니다.
import java.util.*;
class TestAnnotation2{
@SuppressWarnings("unchecked")
public static void main(String args[]){
ArrayList list=new ArrayList();
list.add("sonoo");
list.add("vimal");
list.add("ratan");
for(Object obj:list)
System.out.println(obj);
}
}
해당 코드를 보면 ArrayList에 자료형을 명시해주지 않았습니다.
하지만 해당 어노테이션으로 "unchecked"를 해주면 경고를 무시하고 실행하게 됩니다.
- @Deprecated
코드가 존재하지만 해당 코드를 더이상 사용하지 않거나, 사용할 예정이 당분간 없을 때 해당 어노테이션을 사용해줍니다.(안쓸 코드는 지우면되는데... 추 후 수정을 위해서 적어놓는 것 같습니다.)
해당 어노테이션이 있는 코드를 실행하게 되면 컴파일시 경고 메시지를 뿌려줍니다.
class A{
void m(){System.out.println("hello m");}
@Deprecated
void n(){System.out.println("hello n");}
}
class TestAnnotation3{
public static void main(String args[]){
A a=new A();
a.n();
}
}
output :
Compile by: javac TestAnnotation3.java
86/TestAnnotation3.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
JAVA 커스텀 어노테이션
어노테이션을 프로그래머가 직접 만들 수 있습니다.
그러기 위해선 몇가지 설정을 해줘야 하는데, 설정하는 몇가지 정보를 알려드리겠습니다.
- @Target : 어노테이션을 적용할 위치를 설정합니다.
- @Retention : @Target으로 어노테이션을 적용할 위치를 선정했다면, 해당 어노테이션들을 언제까지 살려둘지 설정합니다.
- @Documented : javadoc2으로 api 문서를 만들 때 어노테이션에 대한 설명도 포함하도록 지정해주는 것입니다.
- @Inherited : 어노테이션을 적용시킨 클래스를 기준으로 상속받게 되면 자식클래스도 어노테이션을 상속 받을 수 있습니다.
- @Repeatable : 어노테이션 정의를 반복적으로 수행할 수 있게 해줍니다.
기본적으로 어노테이션을 만들 때 보통 @Target 과 @Retention 을 같이 써줘야 합니다.
그 이유는 @Target 으로 어느곳을 기준으로 어노테이션 인자 값을 받을지 결정하고, @Retention으로 해당 어노테이션을 어디까지 유지할지 정해야 하기 때문입니다.
때문에 간단하게 예제를 든다면 다음과 같습니다.
Annotation_interface.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD) //필드 타입을 받겠다.
@Retention(RetentionPolicy.RUNTIME) // 실행하는 동안
public @interface Annotation_interface {
String value() default "Hi";
int num() default 10;
}
Annotation_Test.java
import java.lang.reflect.Field;
public class Annotation_Test {
@Annotation_interface()
String s = "first";
@Annotation_interface("hwan")
String name = "second";
int num = 100;
public void anno_fnc(){
System.out.println(name);
System.out.println(num);
}
public static void main(String[] args) {
Annotation_Test at = new Annotation_Test();
Field[] ano_met = Annotation_Test.class.getDeclaredFields();
for(Field e : ano_met){
Annotation_interface a = e.getAnnotation(Annotation_interface.class);
if(a != null) {
System.out.println(a.value() + a.num()); //저장된 어노테이션 값 가져오기
System.out.println(e.getName()); //어노테이션 선언된 변수 이름 가져오기
System.out.println("----------------------");
}
}
}
}
output :
Hi10
s
----------------------
hwan10
name
----------------------
어노테이션 같은 경우에는 메타데이터로 class 파일에 저장됩니다. 때문에 해당 정보를 가져오기 위해선
.class 로 파일을 받아와야 합니다.
위 예제에서 보면 @Target
설정을 .Filed로 했습니다. 때문에 필드에 선언된 변수에 사용할 수 있죠.
@Retention
같은 경우에는 .RUNTIME으로 설정했습니다. 이는 실행중에도 값을 유지한다는 뜻이죠.
때문에 실행 했을 때 출력이 된 것입니다.
그럼 @Target
과 @Retention
부분의 기능들을 알아보도록 하겠습니다.
@Target
ElementType.PACKAGE | 패키지 선언 |
ElementType.TYPE | 타입 선언 |
ElementType.ANNOTATION_TYPE | 어노테이션 타입 선언 |
ElementType.CONSTRUCTOR | 생성자 선언 |
ElementType.FIELD | 멤버 변수 선언 |
ElementType.LOCAL_VARIABLE | 지역 변수 선언 |
ElementType.METHOD | 메서드 선언 |
ElementType.PARAMETER | 전달인자 선언 |
ElementType.TYPE_PARAMETER | 전달인자 타입 선언 |
ElementType.TYPE_USE | 타입 사용 선언 |
@Retention
RetentionPolicy.SOURCE | 컴파일 전까지만 유효하다. |
RetentionPolicy.CLASS | 컴파일러가 클래스를 참조할 때까지 유효하다. |
RetentionPolicy.RUNTIME | 런타임시 까지 계속 유효, 컴파일 이후에도 JVM에 의해 계속 참조가 가능하다.(리플렉션 사용) |
어노테이션 관련 API : docs.oracle.com/javase/8/docs/api/java/lang/annotation/package-summary.html
Java.lang.Class 에 대한 API : docs.oracle.com/javase/7/docs/api/java/lang/Class.html
Java.lang.Class 사용법과 예제를 다룬 사이트 : www.geeksforgeeks.org/class-getdeclaredconstructor-method-in-java-with-examples/
이상입니다.
'프로그래밍 > JAVA' 카테고리의 다른 글
Java Socket을 이용한 흡연감지 서버 프로젝트 입니다. (0) | 2020.11.05 |
---|---|
Java] Console FreeChat 프로그램. (0) | 2020.11.05 |
댓글