organize/자바

Java 32

001cloudid 2024. 8. 20. 16:24
728x90

애너테이션

  • 주석처럼 프로그래밍 언어에 영향을 미치지 않으며, 유용한 정보를 제공
  @Test //이 메소드가 테스트 대상임을 테스트 프로그램에게 알림. JUnit. 단위 테스트 프로그램
  public void method(){
  	...
  }

 

표준 애너테이션

  • 자바에서 제공하는 애너테이션
애너테이션 설명
@Override 컴파일러에게 오버라이딩하는 메소드라는 것을 알림
@Deprecated 앞으로 사용하지 않을 것을 권장하는 대상에 붙임
@SuppressWarnings 컴파일러의 특정 경고메시지가 나타나지 않게 해줌
@SafeVarargs 제네릭 타입의 가변인자에 사용
@FunctionalInterface 함수형 인터페이스라는 것을 알림
@Native native메소드에서 참조되는 상수 앞에 붙임
@Target 애너테이션이 적용가능한 대상을 지정하는데 사용
@Documented 애너테이션 정보가 javadoc으로 작성된 문서에 포함되게 함
@Inherited 애너테이션이 자손 클래스에 상속되도록 함
@Retention 애너테이션이 유지되는 범위를 지정하는데 사용
@Repeatable 애너테이션을 반복해서 적용할 수 있게 함
  • @Override (javac.exe)
    오버라이딩을 올바르게 했는지 컴퍼일러가 체크하게 함
    오버라이딩 할 때 메소드 이름을 잘 못 적는 실수를 하는 경우가 있음
class Parent{
	void parentMethod() {}
}

class Child extends Parent{
	@Override
//	void parentmethod() {} //조상 메소드의 이름 오타
	void parentMethod() {} 
}
  • @Deprecated
    앞으로 사용하지 않을 것을 권장하는 필드나 메소드에 붙임
    예 Date 클래스의 getDate()
    @Deprecated가 붙은 대상이 사용된 코드를 컴파일하면 메시지가 나타남. 에러는 아님
//Date클래스의 getDate()
@Deprecated
public int getDate(){
	return normalize().getDayOfMonth();
}

  • @FunctionalInterface
    함수형 인터페이스에 붙이면, 컴파일러가 올바르게 작성했는지 체크
    함수형 인터페이스에는 하나의 추상메소드만 가져야 한다는 제약이 있음
    ※인터페이스 → 여러개의 추상메소드를 가질 수 있음
interface Testable{
	void test();
	void check();
}
//위의 Testable인터페이스에 @FunctionalInterface를 붙이면 에러 발생 → 하나의 추상 메소드만 가질 수 있기 때문에 test(), check() 중 하나를 제거해야함
0@FunctionalInterface
public interface Runnable{
	void test();//한개의 추상 메소드.
//   void check(); //에러. @FunctionalInterface가 붙은 인터페이스는 하나의 추상메소드만 가질 수 있음
}
  • @SuppressWarnings
    컴퍼일러의 경고메시지가 나타나지 않게 억제함
    괄호() 안에 억제하고자하는 경고의 종류를 문자열로 지정
    둘 이상의 경고를 억제하려면 @SuppressWarnings({"deprecation", "unchecked"}) {}안에 여러개 넣어줌
    -Xlint옵션으로 컴파일하면 경고메시지를 확인할 수 있음. 괄호 []안이 경고의 종류
@SuppressWarnings("unchecked") //제네릭 관련된 경고를 억제
ArrayList list = new ArrayList(); //제네릭 타입을 지정하지 않음
list.add(obj); //여기서 경고발생
public class Study11 {
	@SuppressWarnings("deprecation")
	public static void main(String[] args) {
		
		Child child = new Child();
		child.parentMethod(); //deprecated된 메소드 사용
		
	}

 

메타 에너테이션

  • 애너테이션을 위한 애너테이션
  • java.lang.annotation 패키지에 포함
  • @Target, @Documented, @Inherited, @Retendtion, @Repeatable

 

  • @Target
    애너테이션을 정의할 때, 적용대상 지정에 사용
    ====================================
    대상 타입 : 의미
    ANNOTATION_TYPE : 애너테이션
    CONSTRUCTOR : 생성자
    FIELD : 필드(멤버변수, enum 상수)
    LOCAL_VARIALBE : 지역변수
    METHOD : 메소드
    PACKAGE : 패키지
    PARAMETER : 매개변수
    TYPE : 타입(클래스, 인터페이스, enum)
    TYPE_PARAMETER : 타입 매개변수
    TYPE_USE : 타입이 사용되는 모든 곳
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.TYPE_USE}) //적용대상이 FIELD, TYPE, TYPE_USE
public @interface MyAnnotation{} //MyAnnotation을 정의
@MyAnnotation //적용 대상이 TYPE인 경우
class MyClass{ 
	@MyAnnotation //적용대상이 FIELD인 경우
	int i ;
	@MyAnnotation //적용대상이 TYPE_USE인 경우
	MyClass me;
}
  • @Retention
    애너테이션이 유지(retention)되는 기간을 지정하는 데 사용
    ====================================
    유지정책 : 의미
    SOURCE : 소스파일에만 존재. 클래스파일에는 존재하지 않음
    CLASS : 클래스 파일에 존재. 실행시에 사용불가. 기본값
    RUNTIME : 클래스 파일에 존재. 실행시에 사용가능
    ====================================
    컴파일러에 의해 사용되는 애너테이션의 유지 정책은 SOURCE
    실행시에 사용 가능한 애너테이션의 정책은 RUNTIME
  • @Documented
    javac로 작성한 문서에 포함시키고자 할 때 붙임
@Documented
public @interface FunctionalInterface{}
  • @Inherited
    애너테이션을 자손 클래스에 상속하고자 할 때 붙임
@Inherited //@SuperAnoo가 자손까지 영향 미치게
@interface SuperAnno{}

@SuperAnno
class P{}

class C extends P{} //C에 애너테이션이 붙은 것으로 인식
  • @Repeatable
    반복해서 붙일 수 있는 애너테이션을 정의할 때 사용
    @Repeatable이 붙은 애너테이션은 반복해서 붙일 수 있음
    @Repeatable 하나로 묶을 컨테이너 애너테이션도 정의해야함

 

애너테이션 타입 정의하기

  • 애너테이션을 직접 만들어 사용할 수 있음
@interface 애너테이션이름{
    타입 요소이름(); //애너테이션의 요소를 선언
    ...
}

//ex)
@interface DateTime{
	String yymmdd();
    String hhmmss();
}
  • 애너테이션의 메소드는 추상 메소드이며, 애너테이션을 적용할 때 지정(순서가 없음)
enum TestType{FIRST, FINAL}

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

@TestInfo(
		count=3,
	    testedBy="Kim",
	    testTools={"JUnit","AutoTester"},
	    testType=TestType.FIRST,
	    testDate=@DateTime(yymmdd="240820", hhmmss="165000")
)

 

 

애너테이션의 요소

  • 적용 시 값을 지정하지 않으면, 사용 될 수 있는 기본값 지정 가능(null 제외)
@interface TestInfo1{
	int count() default 1; //기본값을 1로 지정
}
@TestInfo1 //@TestInfo1(count=1)과 동일. default값이 있는경우 생략가능
  • 요소가 하나이고 이름이 value일 때는 요소 이름 생략가능
@interface TestInfo2{
	String value(); 
}
@TestInfo2("passed") //@TestInfo(value="passed")와 동일
  • 요소의 타입이 배열인 경우, 괄호{}를 사용
@interface TestInfo3{
	String[] testTools();
}
//@TestInfo3(testTools={"passed"}) //값이 하나일 경우 @TestInfo3(testTools="passed")와 같이 {} 생략가능
//@TestInfo3(testTools={"Tester1","Tester2"})
@TestInfo3(testTools= {}) //값이 없을 때 {} 반드시 필요

 

모든 애너테이션의 조상

java.lang.annotation.Annotation

  • Annotation은 모든 애너테이션의 조상이지만 상속은 불가
  • Annotation은 인터페이스
    추상메소드를 가지고 있음. 구현할 필요는 없지만 사용 가능
@interface TestInfo4 extends Annotation{} //에러. 허용되지 않은 표현

추상 메소드를 가지고 있음

 

마커 애너테이션

  • 요소가 하나도 정의되지 않은 애너테이션
    ex) @Deprecated

 

애너테이션 요소의 규칙

  • 요소의 타입은 기본형, String, enum, 애너테이션, Class(Class 클래스)만 허용
  • 괄호() 안에 매개변수를 선언할 수 없음
  • 예외를 선언할 수 없음
  • 요소를 타입 매개변수로 정의할 수 없음
package chapter12;

import java.lang.annotation.*;

@Deprecated
@SuppressWarnings("1234") //유효하지 않은 애너테이션은 무시됨
@chapter12.Study13.TestInfo(testedBy="abc", testDate=@chapter12.Study13.DateTime(yymmdd="240820", hhmmss="161500"))
public class Study13 {
	
	public static void main(String[] args) {
		
		Class<Study13> cls = Study13.class; //Study13의 Class객체를 얻음
		
		TestInfo anno = cls.getAnnotation(TestInfo.class);
		System.out.println("anno.testedBy() = " + anno.testedBy());
		System.out.println("anno.testDate().yymmdd() = " + anno.testDate().yymmdd());
		System.out.println("anno.testDate().hhmmss() = " + anno.testDate().hhmmss());
		
		for(String str:anno.testTools()) {
			System.out.println("testTools = " + str);
		}
		
		System.out.println();
		
		Annotation[] annoArr = cls.getAnnotations(); //현재 클래스에 적용된 모든 애너테이션을 가져옴
		for(Annotation annotation : annoArr) {
			System.out.println(annotation);
		}
		
	}
	
@Retention(RetentionPolicy.RUNTIME) //실행 시에 사용 가능하도록 지정
@interface TestInfo{
	int count() default 1;
	String testedBy();
	String[] testTools() default "JUnit";
	TestType testType() default TestType.FIRST;
	DateTime testDate();
}

@Retention(RetentionPolicy.RUNTIME) //실행 시 사용 가능하도록 지정
@interface DateTime{
	String yymmdd();
	String hhmmss();
}

enum TestType{FIRST,FINAL}

}
728x90

'organize > 자바' 카테고리의 다른 글

Java 34  (0) 2024.08.22
Java 33  (0) 2024.08.21
Java 31  (0) 2024.08.15
Java 30  (0) 2024.08.14
Java 29  (0) 2024.08.13