본문 바로가기

개발

Java - 애너테이션

반응형

 @Override
 - 오버라이딩을 올바르게 했는지 컴파일러가 체크하게 한다.
 - 오버라이딩할 때 메서드이름을 잘못적는 실수를 하는 경우가 많다.

class Parent{
	void parentMethod(){}
}

class Child extends Parent {
	// 오버라이딩 하려 했으나 실수로 이름 잘못 적는 경우
	void parentmethod(){
}

 - 오버라이딩할 때는 메서드 선언부에 @Override를 붙이자
    컴파일 시 확인 가능

class Parent{
	void parentMethod(){}
}

class Child extends Parent {
	@Override
	void parentMethod(){ }
}



@Deprecated
 - 앞으로 사용하지 않을 것을 권장하는 필드나 메서드에 붙인다.
 - @Deprecated의 사용 예, Date 클래스의 getDate()

 - @Deprecated 를 사용할 경우 컴파일시 Warning이 나타난다. 
 ide 에서는 안나고 cmd 에서 컴파일시 나타난다.

@FunctionalInterface
 - 함수형 인터페이스에 붙이면, 컴파일러가 올바르게 작성했는지 체크
 - 함수형 인터페이스에는 하나의 추상메서드만 가져야 한다는 제약이 있음 

@SuppressWarnings
 - 컴파일러의 경고메시지가 나타나지 않게 억제한다.
 - 괄호()안에 억제하고자하는 경고의 종류를 문자열로 지정

@SuppressWarnings("unchecked")
void parentMethod() {
	ArrayList list = new ArrayList<>();
	list.add(new Object());
}
// 지네릭스와 관련된 경고를 억제
// 지네릭 타입을 지정하지 않아서 경고가 발생 

 - 둘 이상의 경고를 동시에 억제하려면 다음과 같이 

@SuppressWarnings({"unchecked", "deprecation", "varargs"})

-XlInt 옵션으로 컴파일하면, 경고메시지를 확인할 수 있다.

메타 애너테이션
 - 애너테이션을 만들때 사용하는 애너테이션
 - 메타 애너테이션은 java.lang.annotation패키지에 포함

애너테이션 설명
@Target 애너테이션이 적용가능한 대상을 지정하는데 사용
@Documented 애너테이션 정보가 javadoc으로 작성된 문서에 포함되게 한다.
@Inherited 애너테이션이 자손 클래스에 상속되도록 한다.
@Retention 애너테이션이 유지되는 범위를 지정하는데 사용한다.
@Repeatable 애너테이션을 반복해서 적용할 수 있게 한다.(jdk1.8)

 - @Target
   애너테이션을 정의할 때, 적용대상 지정에 사용
 - @Retention
   애너테이션을 어디까지 남길지 지정

유지 정책 의미
SOURCE 소스 파일에만 존재. 클래스파일에 존재하지 않음.
CLASS 클래스 파일에 존재. 실행시에 사용불가. 기본값
RUNTIME 클래스 파일에 존재. 실행시에 사용가능.

 - @Inheried
 애너테이션을 자손클래스에 상속하고자 할때 사용 

package annotation;

import java.lang.annotation.*;

import static java.lang.annotation.ElementType.*;

// 적용대상
@Target({FIELD, TYPE, TYPE_USE, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
// 어디까지 남길래?
@Retention(RetentionPolicy.SOURCE)  // 소스까지
//@Retention(RetentionPolicy.CLASS)  // 클래스파일까지
//@Retention(RetentionPolicy.RUNTIME)  // 런타임까지
@Documented // javadoc 에 포함
@Inherited  // @SupperAnno가 자손까지 영향 미치게
public @interface MyAnnotation {
}

 

package annotation;

import java.util.ArrayList;

// @MyAnnotation 이 부모 클래스에 있기 때문에 
// 자손클래스 Child에도 이 애너테이션이 붙은 것으로 인식된다.
public class Child extends Parent{
    @Override
    @SuppressWarnings({"unchecked", "deprecation", "varargs"})
    void parentMethod() {
        ArrayList list = new ArrayList<>();
        list.add(new Object());
    }

}

@MyAnnotation // 자손 클래스에 애너테이션 상속시킨다.
class Parent{
    void parentMethod(){


    }
}


 - @Repeatable
 반복해서 붙일 수 있는 애너테이션을 정의할 때 사용 

<반복해서 붙일 수 있는 애너테이션 정의>

package annotation;

import java.lang.annotation.Repeatable;

@Repeatable(ToDos.class)
public @interface ToDo {
    String value();
}

<하나로 묶을 컨테이너 애너테이션 정의>

package annotation;

public @interface ToDos {
    ToDo[] value();
}

<사용>

package annotation;

@ToDo("delete test codes.")
@ToDo("override inherited methods")
public class MyClass {
}

 

 

 

애너테이션 타입 정의하기 
 - 애너테이션을 직접 만들어 쓸 수 있다.

@interface 애너테이션 이름{
	타입 요소이름();	// 애너테이션의 요소를 선언한다.
	...
}

 - 애너테이션의 메서드는 추상메서드이며, 애너테이션을 적용할 때 지정(순서 X)
 - 기본값 지정 가능 dfault 1;

public @interface TestInfo {
        int count() default 1; // 기본값
}

@TestInfo	// @TestInfo(count=1)과 동일
public class NewClass{ }


 - 요소가 하나이고 이름이 value일 때는 요소의 이름 생략 가능

public @interface TestInfo {
	String value();
}

@TestInfo("passed") // @TestInfo(value="passed")와 동일
class NewClass{
	...
}

 - 요소타입이 배열인 경우 괄호{} 사용
 - Annotation은 모든 애너테이션의 조상이지만 상속은 불가 

public @interface TestInfo extends Annotation { // 에러 허용되지 않는 표현
	...
}

 - 사실 Annotation은 인터페이스이다.

예제

package annotation;

enum TestType {FIRST, FINAL}

public @interface TestInfo {
        int count() default 1; // 기본값
        String testedBy();
        String[] testTools();
        TestType testType();	// enum TestType {FIRST, FINAL}
        MyAnnotation testDate();	// 자신이 아닌 다른 애너테이션(@DateTime)을 포함할 수 있다.

}

 사용

package annotation;

@TestInfo(
        count = 3
        , testedBy = "bp"
        , testTools = {"JUnit", "AutoTester"} // 요소타입이 배열인 경우 괄호 사용
        , testType = TestType.FIRST
        , testDate = @MyAnnotation()
)
public class Test {
}

 

애너테이션 요소의 규칙
 - 애너테이션의 요소를 선언할 때 아래의 규칙을 반드시 지켜야 한다.
    요소의 타입은 기본형, String, enum, 애너테이션, Class 만 허용됨
    괄호안에 매개변수를 선언할 수 없다.
    예외를 선언할 수 없다.
    요소를 타입 매개변수로 정의할 수 없다.

 - 아래의 코드에서 잘못된 부분은 무엇인지

@interface AnnoTest {
	int id = 100; 						// ok
    String major(int i, int j); 		// 	에러 매개변수 x
    String minor() throws Exception; 	// 에러 예외선언 x
    ArrayList<T> list();				// 에러 요소를 타입 매개변수로 정의할 수 없다.
}
반응형

'개발' 카테고리의 다른 글

카프카  (0) 2021.08.14
JUnit - 테스트 클래스 생성 및 테스트 실행  (0) 2021.07.11
Java - 열거형(enum)  (0) 2021.06.27
Java - Generics 란  (0) 2021.06.26
Java - Collections의 유용한 static 메서드  (0) 2021.06.06