🏃♂️ 들어가기 앞서..
본 게시물은 스터디 활동 중에 작성한 게시물로 자바의 정석-기초편 교재를 학습하여 정리하는 글입니다.
※ 스터디 Page : 〔투 비 마스터 : 자바〕
*해당 교재의 목차 순서와 구성을 참고하여 작성하며
각 내용마다 부족할 수 있는 내용이나 개인적으로 궁금한 점은
추가적인 검색을 통해 채워나갈 예정입니다.
annotation
)말 그대로 " 주석 "처럼 프로그래밍 언어에 영향을 미치지 않으며 유용한 정보를 제공 하는 것
( "/**
"로 시작하는 주석 → 소스코드 설명 & 미리 정의된@
붙은 태그를 활용해 주석 안에 정보 저장
▶javadoc.exe
프로그램을 통해 문서 작성 )
따로 문서를 작성하고 소스코드가 변경될 때마다 문서도 업데이트 해야했었던 과거와 다르게
한 번에 " 소스코드의 주석 "으로부터 HTML 문서를 생성해 낸다. (javadoc.exe
)
아마 자바 코드들을 지금까지 봐오면서
많이 봤을 것이다.
특히, 재선언하는 Override가 대표적인 애너테이션에 사용되는 요소인데
@Override
라고 Override하는 메서드들 위에 주석같이 달려있는 것을 많이 봤을 것이다.
그것이 바로 애너테이션(annotation) 이다.
" 이 메서드는 Override 하는 것이다. " 라는 것을
일일이 프로그램에게 알려줄 필요없이
@Override
태그로 간단히 붙이면 끝이고
심지어
" 프로그램 컴파일러 "에게 알리는 역할까지 하면서도
메서드가 포함된 프로그램 자체에는 아무 영향을 끼치지 않는다.
( 단, 해당 프로그램에서 미리 정의된 종류와 형식으로 작성해야 의미가 있다. )
자바에서 기본적으로 제공하는 애너테이션
애너테이션 | 설명 |
---|---|
@Override | 해당 메서드를 오버라이딩 하는 것이다. |
@Deprecated | 앞으로 사용하지 않을 것을 권장한다. |
@SuppressWarnings | 컴파일러 특정 경고메세지 차단 |
@SafeVarargs | 지네릭스 타입의 가변인자 사용 |
@FunctionalInterface | 함수형 인터페이스이다. |
@Native | native메서드에서 참조되는 상수 앞에 붙인다. |
[[ 애너테이션을 만들 때 사용 ]] | |
@Taget* | 애너테이션 적용 가능 대상 지정 |
@Documented* | 해당 애너테이션 정보가 javadoc 작성 문자에 포함되게끔 |
@Inherited* | " 자손 클래스 "에상속되도록 |
@Retention* | 애너테이션 유지 범위 지정 |
@Repeatable* | 애너테이션 반복 적용 허용 |
★
-Xlint
사용하기1. 코드 작업 중인 해당 java파일이 위치한 디렉토리의 주소 복사
2. cmd 창 ▶ 해당 디렉토리로 이동
3.
javac 자바파일명.java
컴파일+
javac -Xlint 자바파일명.java
실행하면 더 자세한 내용 확인 가능
@Override
// 상속받을 부모 메서드
class Parent {
void parentMethod() { }
}
class Child extends Parent {
void parentmethod() {} // 이름 틀리게 작성
}
/*
이럴 경우에
컴파일러는 그저 "새로운 이름의 메서드가 추가된 것" 이라고 인식을 하게되서
오류메세지도 발생하지 않고 그냥 넘어가게됨.
*/
class Child extends Parent {
@Override
void parentmethod() {} // 에러 메세지가 발생
}
/*
error : method
does not override or implement a method from a supertype
@Override
^
1 error
라고 본래 목적이였던 "오버라이딩"에 대한 실수라고 컴파일러가 인식할 수 있게 된다.
*/
@Deprecated
새로운 버전으로 JDK가 업데이트 될 때, 새로운 기능 추가 및 기존 기능 개선 등이 되었다고
이미 사용되고 있는 것들을 삭제할 수 없기 때문에
앞으로 사용하지 않는 것이 좋을 것들에 해당 애너테이션을 붙인다.
java.util.Date
클래스 → Java API 에 Deprecated. 라고 작성되어 있다.// 실제 Date클래스의 getDate 메서드 코드
@Deprecated
public int getDate() {
return normalize().getDayOfMonth();
}
@Deprecated
가 붙은 대상을 사용하게 되면 에러가 아닌 Note메세지가 나타난다.Note : Annotation자바파일명 uses or overrides a deprecated API.
Note : Recompile with -Xlint:deprecation for details.
@FunctionalInterface
Override 애너테이션과 유사하게
" 함수형 인터페이스 "를 선언할 때, @FunctionalInterface
를 붙이면
올바르게 선언했는지 확인하고
잘못되었을 때 에러를 발생 시킨다.
( 함수형 인터페이스는 추상메서드가 하나뿐이어야 한다는 제약 )
// 안붙여도 되지만 붙이면 컴파일러의 올바른 작동을 제고시킬 수 있음
@FunctionalInterface
public interface Runaable {
public abstract void run(); // 추상 메서드
}
@SuppressWarnings
/* 잘못됨 */
ArrayList list = new ArrayList();
list.add(obj)
// obj타입을 ArrayList 객체에 add 할때 지네릭 타입을 지정하지 않으면
//지네릭 타입 미지정 unchecked 경고 발생
/* 올바름/애너테이션 활용 */
ArrayList list = new ArrayList<T>();
list.add(obj) ;
@SuppressWarnings("unchecked")
ArrayList list = new ArrayList();
list.add(obj) // 지네릭 타입 미지정 unchecked 경고 발생 억제
@SuppressWarnings({"unchecked", "deprecation", "varargs"})
* "deprecation"
: @Deprecated
붙은 대상을 사용했을 때 경고 발생
* "unchecked"
: 지네릭스로 타입을 지정하지 않았을 때 경고 발생
* "varargs"
: 가변인자 타입이 지네릭 타입일 때 경고 발생
* "rawtypes"
: 지네릭스를 사용하지 않아서 경고 발생
""" 애너테이션을 위한 애너테이션 """
: 애너테이션을 만들 때 사용
(java.lan.annotation
패키지에 포함)
@Target
대상 타입 | 설명 |
---|---|
ANNOTAION_TYPE | 애너테이션 |
CONSTRUCTOR | 생성자 |
FIELD | 필드 ( iv_인스턴스변수 / enum 상수 ) |
LOCAL_VARIABLE | 지역변수 |
METHOD | 메서드 |
PACKAGE | 패키지 |
PARAMETER | 매개변수 |
TYPE | 타입 ( class, interface, enum ) |
《 JDK1.8 ~ 》 | |
TYPE_PARAMETER | 타입 매개변수 |
TYPE_USE | 타입이 사용되는 모든 곳 |
앞서 알아봤던 SuppressWarnings 애너테이션의 경우를 살펴보면
/*
SuppressWarnings 애너테이션 ( @SuppressWarnings )이 적용될 수 있는 대상을 지정해줌
*/
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
// 클래스,인터페이스,enum, 멤버변수, enum 상수, 매개변수, 메서드, 생성자, 지역변수에 적용할 수 있게끔
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value() ;
}
@Retention
@Retention( RetentionPolicy.유지기준)
유지 기준 | 의미 |
---|---|
SOURCE | " 소스파일에만 존재 "_ 클래스 파일에 X ( 애너테이션 정보가 클래스 파일에 남아있지 않음. ) |
CLASS [기본값] | " 클래스 파일에 존재 " → 실행시 사용 불가 |
RUNTIME | " 클래스 파일에 존재 " → 실행시 사용 가능 |
Override 애너테이션의 경우를 살펴보면 이러하다.
/*
Override 애너테이션 : Override 체킹만 해주고 클래스 파일엔 저장되지 않는 애너테이션
*/
@Target( ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {}
반면 FunctionalInterface 애너테이션은 클래스 파일에까지 저장되는
RUNTIME 기준을 사용한다.
/*
FunctionalInterface 애너테이션
*/
@Documented
@Target( ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface FunctionalInterface {}
@Documented
/ @Inherited
@Documented
= javadoc
으로 작성한 문서에 " 포함시키려면 "
( @Override
와 @FunctionalInterface
를 제외하고 모두 붙어있음 )
@Inherited
= 자손 클래스에까지 같이 상속되게끔
@Inherited
@interface MyAnno{}
@MyAnno
class Parent{}
class Child extends Parent{} // Parent클래스에 붙어있던 MyAnno가 동일하게 붙어있는 효력
@Repeatable
한 클래스에 @Repeatable
이 붙은 애너테이션을 여러개 중복해서 붙일 수 있다.
단, 같은 이름의 애너테이션이 중복해서 달려있는 것이 가능하기 때문에
하나로 묶어서 다룰 수 있는 애너테이션도 같이 정의해주어야한다.
( 배열타입의 요소의 이름 = " 반드시 value " )
/* 여러개의 애너테이션을 담을 "컨테이너 애너테이션" */
@interface ToDos {
ToDo[] value(); // 반드시 value
}
/* Repeatable 한 애너테이션 */
@Repeatable(ToDos.class) // 컨테이너 애너테이션 지정해줘야 함.
@interface ToDo {
String value();
}
@ToDo("update codes")
@ToDo("override inherited methods")
// 더 추가할 수 있음.
class MyClass {
...
}