English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Java Basic Tutorial

Java flow control

Java array

Java object-oriented (I)

Java object-oriented (II)

Java object-oriented (III)

Java Exception Handling

Java List

Java Queue (queue)

Java Map collection

Java Set collection

Java input/output (I)/O)

Java Reader/Writer

Java other topics

Java annotation types

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

Predefined annotation types

1. @Deprecated

@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() { ... }

Example1: @Deprecated annotation example

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

2. @Override

@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).

Example2Example of @Override annotation

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.

3. @SuppressWarnings

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")

Example3: @SuppressWarnings annotation example

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.

4. @SafeVarargs

@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.

Example4: @SafeVarargs annotation example

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) { ... }

我们得到相同的输出,但没有任何警告。当使用此注解时,未经检查的警告也会被删除。

5. @FunctionalInterface

Java 8首先引入了此@FunctionalInterface注解。此注解表明使用它的类型声明是一个功能接口。一个功能接口只能有一个抽象方法。

Example5:@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() { ... } 
}

Custom annotations

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.

Example6:Custom annotation example

@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

Meta-annotations are annotations that are applied to other annotations.

1. @Retention

@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{ ... }

2. @Documented

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{ ... }

3. @Target

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 typeTarget
ElementType.ANNOTATION_TYPEAnnotation type
ElementType.CONSTRUCTORConstructor
ElementType.FIELDField
ElementType.LOCAL_VARIABLELocal variable
ElementType.METHODMethod
ElementType.PACKAGEPackage
ElementType.PARAMETERParameter
ElementType.TYPEUsed 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.

4. @Inherited

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 { ... }

5. @Repeatable

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.