English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
В этом учебнике мы изучим различные типы Java аннотаций с помощью примеров.
Java аннотации - это метаданные нашего программного кода (данные о данных). Java SE предоставляет несколько предопределенных аннотаций. Кроме того, мы можем создавать пользовательские аннотации по мере необходимости.
Если вы не знаете, что такое аннотация, пожалуйста, обратитесь вJava 애너테이션учебник
Эти аннотации можно классифицировать как:
1. предопределенные аннотации
@Deprecated
@Override
@SuppressWarnings
@SafeVarargs
@FunctionalInterface
2. 自定义注解
3. 元注解
@Retention
@Documented
@Target
@Inherited
@Repeatable
@Deprecated 표시는 요소(클래스, 메서드, 필드 등)가 오래된 것으로 대체된 것을 나타내는 표시 표시입니다.
그 문법은 다음과 같습니다:
@Deprecated accessModifier returnType deprecatedMethodName() { ... }
프로그램이 이미 폐지된 요소를 사용할 때, 컴파일러는 경고를 생성합니다.
우리는 Javadoc @deprecated 표시를 사용하여 폐지된 요소를 기록합니다.
/** * @deprecated * 그래서 왜 폐지되었는지 */ @Deprecated accessModifier returnType deprecatedMethodName() { ... }
class Main { /** * @deprecated * 此方法已弃用,并已由newMethod()代替 */ @Deprecated public static void deprecatedMethod() { System.out.println("버전된 메서드"); } public static void main(String args[]) { deprecatedMethod(); } }
输出结果
버전된 메서드
@Override 注解指定子类的方法用相同的方法名、返回类型和参数列表覆盖父类的方法。
@Override在重写方法时,并非必须使用。 但是,如果使用它,则在覆盖方法时,如果出现错误(例如错误的参数类型),则编译器将给出错误。
class Animal { //重写方法 public void display(){ System.out.println("I am an animal"); } } class Dog extends Animal { //重写方法 @Override public void display(){ System.out.println("I am a dog"); } public void printMessage(){ display(); } } class Main { public static void main(String[] args) { Dog dog1 = new Dog(); dog1.printMessage(); } }
输出结果
I am a dog
在本示例中,通过创建Dog类的对象dog1,我们可以调用它的方法printMessage(),然后该方法执行display()语句。
由于display()在两个类中均已定义,因此Dog子类的display()方法将覆盖超类Animal的display()方法。因此,子类的display()被调用。
顾名思义,@SuppressWarnings注解指示编译器禁止执行程序时生成的警告。
我们可以指定要取消的警告类型。可以禁止的警告是特定于编译器的,但警告分为两类:弃用 和 未检查。
为了禁止显示特定类别的警告,我们特意使用:
@SuppressWarnings("warningCategory")
예를 들어,
@SuppressWarnings("deprecated")
为了禁止显示多个类别警告,我们特意使用:
@SuppressWarnings("warningCategory1", "warningCategory2"})
예를 들어,
@SuppressWarnings({"deprecated", "unchecked"})
当我们使用不建议使用的元素时,deprecated类别指示编译器禁止显示警告。
기본 타입을 사용할 때, unchecked 카테고리는 컴파일러에게 경고를 표시하지 않도록 지시합니다.
또한, 정의되지 않은 경고는 무시됩니다. 예를 들어,
@SuppressWarnings("someundefinedwarning")
class Main { @Deprecated public static void deprecatedMethod() { System.out.println("버전된 메서드"); } @SuppressWarnings("deprecated") public static void main(String args[]) { Main depObj = new Main(); depObj. deprecatedMethod(); } }
输出结果
버전된 메서드
여기서 deprecatedMethod()는 버전되었습니다. 사용할 때 컴파일러 경고가 발생합니다. @SuppressWarnings("deprecated")를 사용하여 컴파일러 경고를 피할 수 있습니다.
@SafeVarargs 注解cassert, 가시닉 메서드나 생성자는 그의 변경 가능한 매개변수를 안전하지 않은 작업을 수행하지 않는다고 주장합니다.
우리는 재정의될 수 없는 메서드나 생성자에만 이를 사용할 수 있습니다. 그렇지 않으면 재정의된 메서드가 불안전한 작업을 수행할 수 있습니다.
Java에서 9이전에는 이 注解를 final 또는 static 메서드에만 사용할 수 있었습니다. 그들은 재정의될 수 없기 때문입니다. 지금은 이를 개인 메서드에도 사용할 수 있습니다.
import java.util.*; class Main { private void displayList(List<String>... lists) { for (List<String> list : lists) { System.out.println(list); } } public static void main(String args[]) { Main obj = new Main(); List<String> universityList = Arrays.asList("Tribhuvan University", "Kathmandu University"); obj.displayList(universityList); List<String> programmingLanguages = Arrays.asList("Java", "C"); obj.displayList(universityList, programmingLanguages); } }
경고 사항
Type safety: varargs 매개변수 목록을 통해 가능한 heap pollution Type safety: varargs 매개변수로 List<String>의 generic 배열이 생성됩니다 parameter
输出结果
Note: Main.java는 unchecked 또는 unsafe operations을 사용합니다. [Tribhuvan University, Kathmandu University] [Tribhuvan University, Kathmandu University] [Java, C]
이 경우 List ... list는 List 타입의 변형 가능한 매개변수로 지정됩니다. 이는 displayList() 메서드가 0개나 많은 매개변수를 가질 수 있음을 의미합니다.
위 프로그램은 컴파일 오류가 없지만, @SafeVarargs 注해를 사용하지 않을 때 경고가 발생합니다.
위 예제에서 @SafeVarargs 注해를 사용할 때,
@SafeVarargs private void displayList(List<String>... lists) { ... }
이제 같은 출력을 얻지만 경고는 없습니다. 이 注해를 사용할 때, 확인되지 않은 경고도 제거됩니다.
Java 8먼저 이 @FunctionalInterface 注解을 소개합니다. 이 注해는 그것을 사용하는 타입이 functional interface라는 것을 의미합니다. functional interface는 하나의 abstract method만 가질 수 있습니다.
@FunctionalInterface public interface MyFuncInterface{ public void firstMethod(); //이는 abstract method입니다 }
또 다른 abstract method를 추가하면
@FunctionalInterface public interface MyFuncInterface{ public void firstMethod(); // 이는 abstract method입니다 public void secondMethod(); //이는 컴파일 오류를 일으킵니다 }
이제, 프로그램을 실행할 때, 다음과 같은 경고를 받게 됩니다:
Unexpected @FunctionalInterface annotation @FunctionalInterface ^ MyFuncInterface 는 functional interface가 아닙니다 non-MyFuncInterface 인터페이스에서 발견된 overriding abstract methods
使用@FunctionalInterface注解不是强制性的。编译器会将满足功能接口定义的任何接口视为功能接口。
我们使用此注解的目的,是确保功能接口只有一种抽象方法。
但是,它可以有任意数量的默认方法和静态方法,因为它们都有实现。
@FunctionalInterface public interface MyFuncInterface{ public void firstMethod(); //这是一种抽象方法 default void secondMethod() { ... } default void thirdMethod() { ... } }
也可以创建我们自己的自定义注解。
그 문법은 다음과 같습니다:
[Access Specifier] @interface<AnnotationName> { DataType <Method Name>() [default value]; }
这是您需要了解的有关自定义注解的信息:
注解可以通过使用@interface后面跟注解名称来创建。
注解可以具有看起来像方法的元素,但是它们没有实现。
默认值是可选的。参数不能为空值。
方法的返回类型可以是原始,枚举,字符串,类名或这些类型的数组。
@interface MyCustomAnnotation { String value() default "default value"; } class Main { @MyCustomAnnotation(value = "w3codebox") public void method1() { System.out.println("测试方法1"); } public static void main(String[] args) throws Exception { Main obj = new Main(); obj.method1(); } }
输出结果
测试方法1
元注解是应用于其他注解的注解。
@Retention注解指定了该注解可用的最高级别。
그 문법은 다음과 같습니다:
@Retention(RetentionPolicy)
有三种类型:
RetentionPolicy.SOURCE - 注解仅在源级别可用,并且被编译器忽略。
RetentionPolicy.CLASS - 어노테이션은 컴파일 시에 컴파일러가 사용할 수 있지만, Java virtually machine(JVM)은 무시합니다.
RetentionPolicy.RUNTIME - 어노테이션은 JVM에서 사용할 수 있습니다.
예를 들어,
@Retention(RetentionPolicy.RUNTIME) public @interface MyCustomAnnotation{ ... }
기본적으로, 사용자 정의 어노테이션은 공식 Java 문서에 포함되지 않습니다. 어노테이션을 Javadoc 문서에 포함하려면 @Documented 어노테이션을 사용하십시오.
예를 들어,
@Documented public @interface MyCustomAnnotation{ ... }
우리는 @Target 어노테이션을 사용하여 어노테이션을 특정 대상에 제한할 수 있습니다.
그 문법은 다음과 같습니다:
@Target(ElementType)
ElementType는 다음과 같은 유형 중 하나일 수 있습니다:
요소 타입 | Target |
---|---|
ElementType.ANNOTATION_TYPE | 어노테이션 타입 |
ElementType.CONSTRUCTOR | 생성자 |
ElementType.FIELD | 필드 |
ElementType.LOCAL_VARIABLE | 지역 변수 |
ElementType.METHOD | 메서드 |
ElementType.PACKAGE | 패키지 |
ElementType.PARAMETER | 파라미터 |
ElementType.TYPE | 클래스, 인터페이스(어노테이션 타입 포함) 또는 enum 선언을 설명하는 데 사용됩니다 |
예를 들어,
@Target(ElementType.METHOD) public @interface MyCustomAnnotation{ ... }
이 예제에서는 이 어노테이션의 사용을 메서드에 제한했습니다.
주의:목표 타입이 정의되지 않았을 경우, 어노테이션은 어떤 요소에도 적용할 수 있습니다.
기본적으로, 어노테이션 타입은 상위 클래스에서 상속받을 수 없습니다. 그러나 어노테이션을 상위 클래스에서 자식 클래스로 상속시키려면 @Inherited 어노테이션을 사용할 수 있습니다.
그 문법은 다음과 같습니다:
@Inherited
예를 들어,
@Inherited public @interface MyCustomAnnotation { ... } @MyCustomAnnotation public class ParentClass{ ... } public class ChildClass extends ParentClass { ... }
Repeatable 표시자를 가진 어노테이션은 동일한 선언에 여러 번 적용할 수 있습니다.
@Repeatable(Universities.class)} public @interface University { String name(); }
@Repeatable 애너테이션에서 정의된 값은 컨테이너 애너테이션입니다. 컨테이너 애너테이션은 위에서 설명된 재사용 가능한 애너테이션 배열类型的 변수 값(value)을 가집니다. 여기서 Universities는 애너테이션 타입을 포함하는 것입니다.
public @interface Universities { University[] value(); }
이제, @University 애너테이션은 동일한 선언에서 여러 번 사용할 수 있습니다.
@University(name = "TU") @University(name = "KU") private String uniName;
애너테이션 데이터를 검색하려면, 다음을 사용할 수 있습니다:리플렉션。
애너테이션 값을 검색하려면, 리플렉션 API에서 정의된 getAnnotationsByType() 또는 getAnnotations() 메서드를 사용합니다.