1. 개요
이 기사에서는 JDK에서 사용할 수있는 기본 주석 인 Java 언어의 핵심 기능에 대해 설명합니다.
2. 주석이란?
간단히 말해, 주석은 "@"기호가 앞에 오는 Java 유형입니다 .
Java는 1.5 릴리스 이후로 주석을 달았습니다. 그 이후로 그들은 우리가 응용 프로그램을 설계하는 방식을 형성했습니다.
Spring과 Hibernate는 다양한 디자인 기술을 가능하게하기 위해 주석에 크게 의존하는 프레임 워크의 훌륭한 예입니다.
기본적으로 주석은 바인딩 된 소스 코드에 추가 메타 데이터를 할당합니다 . 메소드, 인터페이스, 클래스 또는 필드에 주석을 추가하여 다음을 수행 할 수 있습니다.
- 경고 및 오류에 대해 컴파일러에 알립니다.
- 컴파일 타임에 소스 코드 조작
- 런타임시 동작 수정 또는 검사
3. 자바 내장 주석
이제 기본 사항을 검토 했으므로 핵심 Java와 함께 제공되는 몇 가지 주석을 살펴 보겠습니다. 첫째, 컴파일을 알리는 몇 가지가 있습니다.
- @우세하다
- 안녕하세요.
- @Deprecated
- 뿡 빵뀨
- @FunctionalInterface
- @원주민
이러한 주석은 컴파일러 경고 및 오류를 생성하거나 억제합니다. 이를 추가하면 향후 프로그래머의 오류를 방지 할 수 있으므로 일관되게 적용하는 것이 좋습니다.
@Override의 주석을 표시하기 위해 사용되는 방법을 대체 또는 대체하는 상속 된 메소드의 동작.
@SuppressWarnings 는 코드의 일부에서 특정 경고를 무시하려고 함을 나타냅니다. @SafeVarargs 주석은 또한 가변 인자를 사용하여 관련 경고의 유형에 역할을합니다.
@Deprecated 어노테이션은 더 이상 사용하기위한 것이 아닙니다 같은 API를 표시하는 데 사용할 수 있습니다. 또한이 주석은 사용 중단에 대한 자세한 정보를 나타 내기 위해 Java 9 에서 개조되었습니다 .
이 모든 것에 대해 링크 된 기사에서 더 자세한 정보를 찾을 수 있습니다.
3.1. @FunctionalInterface
Java 8을 사용하면보다 기능적인 방식으로 코드를 작성할 수 있습니다.
단일 추상 메소드 인터페이스 는 이것의 큰 부분입니다. SAM 인터페이스를 람다에서 사용하려는 경우 선택적으로 @FunctionalInterface 로 표시 할 수 있습니다 .
@FunctionalInterface
public interface Adder {
int add(int a, int b);
}
메서드가있는 @Override 와 마찬가지로 @FunctionalInterface 는 Adder를 사용 하여 우리의 의도를 선언합니다 .
이제 @FunctionalInterface 사용 여부에 관계없이 동일한 방식으로 Adder 를 사용할 수 있습니다 .
Adder adder = (a,b) -> a + b;
int result = adder.add(4,5);
그러나 Adder에 두 번째 메서드를 추가 하면 컴파일러가 다음과 같이 불평합니다.
@FunctionalInterface
public interface Adder {
// compiler complains that the interface is not a SAM
int add(int a, int b);
int div(int a, int b);
}
이제 이것은 @FunctionalInterface 주석 없이 컴파일되었을 것 입니다. 그래서 그것은 우리에게 무엇을 제공합니까?
@Override 와 마찬가지로이 주석은 향후 프로그래머 오류로부터 우리를 보호합니다. 인터페이스에 둘 이상의 메서드가있는 것은 합법적이지만 해당 인터페이스가 람다 대상으로 사용되는 경우는 아닙니다. 이 주석이 없으면 컴파일러는 Adder 가 람다로 사용 된 수십 곳에서 중단됩니다 . 이제 Adder 자체 에서 중단 됩니다.
3.2. @원주민
Java 8 부터는 java.lang.annotation 패키지에 Native 라는 새 주석이 있습니다. @Native 주석 필드에만 적용 할 수 있습니다. 주석이 달린 필드가 네이티브 코드에서 참조 할 수있는 상수임을 나타냅니다 . 예를 들어, Integer 클래스 에서 사용되는 방법은 다음과 같습니다.
public final class Integer {
@Native public static final int MIN_VALUE = 0x80000000;
// omitted
}
이 주석은 도구가 일부 보조 헤더 파일을 생성하기위한 힌트로도 사용할 수 있습니다.
4. 메타 주석
다음으로 메타 주석은 다른 주석에 적용 할 수있는 주석입니다.
예를 들어 다음 메타 주석은 주석 구성에 사용됩니다.
- @표적
- @보유
- 상속
- @ 문서화
- @Repeatable
4.1. @표적
주석의 범위는 요구 사항에 따라 다를 수 있습니다. 하나의 주석은 메서드에만 사용되지만 다른 주석은 생성자 및 필드 선언과 함께 사용할 수 있습니다.
사용자 지정 주석의 대상 요소를 결정하려면 @Target 주석 으로 레이블을 지정해야합니다 .
@Target 은 12 개의 다른 요소 유형 과 함께 작동 할 수 있습니다 . @SafeVarargs 의 소스 코드를 살펴보면 생성자 또는 메서드에만 첨부되어야 함을 알 수 있습니다.
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface SafeVarargs {
}
4.2. @보유
일부 주석은 컴파일러의 힌트로 사용되는 반면 다른 주석은 런타임에 사용됩니다.
@Retention 어노테이션을 사용하여 프로그램 라이프 사이클에서 어노테이션이 적용되는 위치를 지정 합니다.
이렇게하려면 세 가지 보존 정책 중 하나 를 사용하여 @Retention 을 구성해야합니다 .
- RetentionPolicy.SOURCE – 컴파일러 나 런타임 모두에서 볼 수 없습니다.
- RetentionPolicy.CLASS – 컴파일러에서 볼 수 있습니다.
- RetentionPolicy.RUNTIME – 컴파일러 및 런타임에 표시
주석 선언에 @Retention 주석이 없는 경우 보존 정책의 기본값은 RetentionPolicy.CLASS 입니다.
런타임에 액세스 할 수 있어야하는 주석이있는 경우 :
@Retention(RetentionPolicy.RUNTIME)
@Target(TYPE)
public @interface RetentionAnnotation {
}
그런 다음 클래스에 주석을 추가하면 :
@RetentionAnnotation
@Generated("Available only on source code")
public class AnnotatedClass {
}
이제 AnnotatedClass 에 반영하여 얼마나 많은 주석이 유지되는지 확인할 수 있습니다 .
@Test
public void whenAnnotationRetentionPolicyRuntime_shouldAccess() {
AnnotatedClass anAnnotatedClass = new AnnotatedClass();
Annotation[] annotations = anAnnotatedClass.getClass().getAnnotations();
assertThat(annotations.length, is(1));
}
@RetentionAnnotation 에는 RUNTIME 보존 정책이 있지만 @Generated 에는 그렇지 않으므로 값은 1 입니다.
4.3. 상속
어떤 상황에서는 어노테이션을 부모 클래스에 바인딩하기 위해 서브 클래스가 필요할 수 있습니다.
@Inherited 어노테이션을 사용하여 어노테이션이 어노테이션이있는 클래스에서 하위 클래스로 전파되도록 할 수 있습니다 .
우리가 적용 할 경우 @Inherited 다음 우리의 사용자 정의 주석과에 적용 BaseClass로 :
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface InheritedAnnotation {
}
@InheritedAnnotation
public class BaseClass {
}
public class DerivedClass extends BaseClass {
}
그런 다음 BaseClass를 확장 한 후 DerivedClass 가 런타임에 동일한 주석을 갖는 것으로 나타납니다.
@Test
public void whenAnnotationInherited_thenShouldExist() {
DerivedClass derivedClass = new DerivedClass();
InheritedAnnotation annotation = derivedClass.getClass()
.getAnnotation(InheritedAnnotation.class);
assertThat(annotation, instanceOf(InheritedAnnotation.class));
}
@Inherited 주석이 없으면 위의 테스트가 실패합니다.
4.4. @ 문서화
기본적으로 Java는 Javadocs의 주석 사용을 문서화하지 않습니다.
그러나 @Documented 주석을 사용하여 Java의 기본 동작을 변경할 수 있습니다 .
@Documented 를 사용하는 사용자 지정 주석을 만드는 경우 :
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelCell {
int value();
}
그리고 적절한 Java 요소에 적용하십시오.
public class Employee {
@ExcelCell(0)
public String name;
}
그런 다음 Employee Javadoc이 주석 사용법을 표시합니다.
4.5. @Repeatable
때때로 주어진 Java 요소에 동일한 어노테이션을 두 번 이상 지정하는 것이 유용 할 수 있습니다.
Java 7 이전에는 주석을 단일 컨테이너 주석으로 그룹화해야했습니다.
@Schedules({
@Schedule(time = "15:05"),
@Schedule(time = "23:00")
})
void scheduledAlarm() {
}
그러나 Java 7은 더 깨끗한 접근 방식을 가져 왔습니다. 로 @Repeatable 주석, 우리는 주석 반복을 할 수 있습니다 :
@Repeatable(Schedules.class)
public @interface Schedule {
String time() default "09:00";
}
@Repeatable 을 사용하려면 컨테이너 주석도 필요합니다 . 이 경우 @Schedules를 재사용 합니다 .
public @interface Schedules {
Schedule[] value();
}
물론 이것은 Java 7 이전과 비슷해 보이지만 이제 값은 @Schedule 을 반복해야 할 때 래퍼 @Schedules 가 더 이상 지정되지 않는다는 것입니다 .
@Schedule
@Schedule(time = "15:05")
@Schedule(time = "23:00")
void scheduledAlarm() {
}
Java에는 래퍼 주석이 필요하기 때문에 Java 7 이전 주석 목록에서 반복 가능한 주석으로 쉽게 마이그레이션 할 수있었습니다.
5. 결론
이 기사에서는 모든 Java 개발자가 숙지해야하는 Java 내장 주석에 대해 설명했습니다.
항상 그렇듯이 기사의 모든 예제는 GitHub 에서 찾을 수 있습니다 .