English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
In this tutorial, we will learn different types of Java annotations with examples.
Java annotations are metadata of our program source code (data about data). Java SE provides several predefined annotations. In addition, we can also create custom annotations as needed.
If you don't know what annotations are, please visitJava AnnotationsTutorial.
These annotations can be categorized as:
1. Predefined annotations
@Deprecated
@Override
@SuppressWarnings
@SafeVarargs
@FunctionalInterface
2. Custom annotations
3. Meta-annotations
@Retention
@Documented
@Target
@Inherited
@Repeatable
@Deprecated annotation is a marker annotation indicating that an element (class, method, field, etc.) is outdated and has been replaced by an updated element.
The syntax is as follows:
@Deprecated accessModifier returnType deprecatedMethodName() { ... }
When the program uses elements declared as deprecated, the compiler will generate warnings.
We use the Javadoc @deprecated tag to record deprecated elements.
/** * @deprecated * Why is it deprecated */ @Deprecated accessModifier returnType deprecatedMethodName() { ... }
class Main { /** * @deprecated * This method is deprecated and has been replaced by newMethod() */ @Deprecated public static void deprecatedMethod() { System.out.println("Deprecated method"); } public static void main(String args[]) { deprecatedMethod(); } }
Output result
Deprecated method
@Override annotation specifies that the method of the subclass uses the same method name, return type, and parameter list to override the method of the superclass.
@Override is not required when overriding methods. However, if it is used, the compiler will give an error if there is an error in overriding the method (such as incorrect parameter type).
class Animal { //Override method public void display(){ System.out.println("I am an animal"); } } class Dog extends Animal { //Override method @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(); } }
Output result
I am a dog
In this example, by creating an object of the Dog class, dog1We can call its method printMessage(), and then this method executes the display() statement.
Since the display() method is defined in both classes, the display() method of the Dog subclass will override the display() method of the superclass Animal. Therefore, the subclass's method is called.
As the name implies, the @SuppressWarnings annotation indicates that the compiler prohibits warnings generated when the program is executed.
We can specify the types of warnings to be canceled. The warnings that can be disabled are specific to the compiler, but warnings are divided into two categories:deprecated and unchecked.
To disable displaying warnings for specific categories, we deliberately use:
@SuppressWarnings("warningCategory")
For example,
@SuppressWarnings("deprecated")
To disable displaying multiple category warnings, we deliberately use:
@SuppressWarnings("warningCategory1", "warningCategory2"}
For example,
@SuppressWarnings({"deprecated", "unchecked"})
When using elements that are not recommended, the deprecated category indicates that the compiler prohibits displaying warnings.
when we use primitive types, the unchecked category indicates to the compiler to prohibit displaying warnings.
And, undefined warnings will be ignored. For example,
@SuppressWarnings("someundefinedwarning")
class Main { @Deprecated public static void deprecatedMethod() { System.out.println("Deprecated method"); } @SuppressWarnings("deprecated") public static void main(String args[]) { Main depObj = new Main(); depObj.deprecatedMethod(); } }
Output result
Deprecated method
Here, deprecatedMethod() has been marked as deprecated, and a compiler warning is issued when used. By using the @SuppressWarnings("deprecated") annotation, we can avoid the compiler warning.
@SafeVarargs annotation asserts that the annotated method or constructor does not perform any unsafe operations on its variable arguments (variable number of arguments).
we can only use this annotation on methods or constructors that cannot be overridden. This is because overriding them might perform unsafe operations.
In Java 9Previously, we could only use this annotation on final or static methods, because they cannot be overridden. Now, we can also use this annotation on private methods.
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); } }
警告事项
类型安全:通过varargs参数列表的潜在堆污染 类型安全:为varargs创建了一个List<String>的泛型数组 参数
Output result
注意:Main.java使用了未经检查或不可靠的操作。 [Tribhuvan University, Kathmandu University] [Tribhuvan University, Kathmandu University] [Java, C]
在此,List ... list指定类型为List的变长参数。 这意味着方法displayList()可以具有零个或多个参数。
上面的程序编译没有错误,但是在不使用@SafeVarargs 注解时会发出警告。
在上面的示例中使用@SafeVarargs注解时,
@SafeVarargs private void displayList(List<String>... lists) { ... }
我们得到相同的输出,但没有任何警告。当使用此注解时,未经检查的警告也会被删除。
Java 8首先引入了此@FunctionalInterface注解。此注解表明使用它的类型声明是一个功能接口。一个功能接口只能有一个抽象方法。
@FunctionalInterface public interface MyFuncInterface{ public void firstMethod(); //这是一个抽象的方法 }
如果我们添加另一个抽象方法,那么
@FunctionalInterface public interface MyFuncInterface{ public void firstMethod(); // 这是一个抽象的方法 public void secondMethod(); //这将引发编译错误 }
现在,当我们运行程序时,我们将收到以下警告:
意外的@FunctionalInterface注解 @FunctionalInterface ^ MyFuncInterface不是一个功能接口 多个非-重写接口MyFuncInterface中找到的抽象方法
Using the @FunctionalInterface annotation is not mandatory. The compiler will treat any interface that meets the functional interface definition as a functional interface.
The purpose of using this annotation is to ensure that the functional interface has only one abstract method.
However, it can have any number of default methods and static methods, because they all have implementations.
@FunctionalInterface public interface MyFuncInterface{ public void firstMethod(); //This is an abstract method default void secondMethod() { ... } default void thirdMethod() { ... } }
We can also create our own custom annotations.
The syntax is as follows:
[Access Specifier] @interface<AnnotationName> { DataType <MethodName>() [default value]; }
Here is the information you need to know about custom annotations:
Annotations can be created by using @interface followed by the annotation name.
Annotations can have elements that look like methods, but they do not have an implementation.
The default value is optional. The parameter cannot be null.
The return type of a method can be primitive, enum, string, class name, or an array of these types.
@interface MyCustomAnnotation { String value() default "default value"; } class Main { @MyCustomAnnotation(value = "w3codebox) public void method1() { System.out.println("Test method1"); } public static void main(String[] args) throws Exception { Main obj = new Main(); obj.method1(); } }
Output result
Test method1
Meta-annotations are annotations that are applied to other annotations.
@Retention annotation specifies the highest level at which the annotation is available.
The syntax is as follows:
@Retention(RetentionPolicy)
There are three types:
RetentionPolicy.SOURCE - Annotations are only available at the source level and are ignored by the compiler.
RetentionPolicy.CLASS - Annotations are available to the compiler at compile time, but the Java Virtual Machine (JVM) ignores them.
RetentionPolicy.RUNTIME - Annotations can be used by JVM.
For example,
@Retention(RetentionPolicy.RUNTIME) public @interface MyCustomAnnotation{ ... }
By default, custom annotations are not included in the official Java documentation. To include annotations in the Javadoc documentation, use the @Documented annotation.
For example,
@Documented public @interface MyCustomAnnotation{ ... }
We can use the @Target annotation to restrict the annotation to be applied to a specific target.
The syntax is as follows:
@Target(ElementType)
ElementType can be one of the following types:
Element type | Target |
---|---|
ElementType.ANNOTATION_TYPE | Annotation type |
ElementType.CONSTRUCTOR | Constructor |
ElementType.FIELD | Field |
ElementType.LOCAL_VARIABLE | Local variable |
ElementType.METHOD | Method |
ElementType.PACKAGE | Package |
ElementType.PARAMETER | Parameter |
ElementType.TYPE | Used to describe class, interface (including annotation types) or enum declarations |
For example,
@Target(ElementType.METHOD) public @interface MyCustomAnnotation{ ... }
In this example, we limit the use of this annotation to methods only.
Note:If the target type is not defined, the annotation can be used for any element.
By default, annotation types cannot be inherited from superclasses. However, if it is necessary to inherit annotations from a superclass to a subclass, the @Inherited annotation can be used.
The syntax is as follows:
@Inherited
For example,
@Inherited public @interface MyCustomAnnotation { ... } @MyCustomAnnotation public class ParentClass{ ... } public class ChildClass extends ParentClass { ... }
Annotations marked with @Repeatable can be applied multiple times to the same declaration.
@Repeatable(Universities.class)} public @interface University { String name(); }
The value defined in the @Repeatable annotation is a container annotation. Container annotations have the variable value (value) of the above repeatable annotation array type. Here, Universities is the container of annotation types.
public @interface Universities { University[] value(); }
Now, the @University annotation can be used multiple times on the same declaration.
@University(name = "TU") @University(name = "KU") private String uniName;
If you need to retrieve annotation data, you can useReflection.
To retrieve annotation values, we use the getAnnotationsByType() or getAnnotations() method defined in the reflection API.