📜  Java中的注解

📅  最后修改于: 2022-05-13 01:54:27.767000             🧑  作者: Mango

Java中的注解

注释用于提供有关程序的补充信息。

  • 注释以“ @ ”开头。
  • 注释不会改变已编译程序的操作。
  • 注释有助于将元数据(信息)与程序元素相关联,即实例变量、构造函数、方法、类等。
  • 注释不是纯粹的注释,因为它们可以改变编译器处理程序的方式。例如,请参见下面的代码。
  • 注释基本上用于提供附加信息,因此可以替代 XML 和Java标记接口。

Java中的注解层次结构

执行:

例子:

Java
// Java Program to Demonstrate that Annotations
// are Not Barely Comments
 
// Class 1
class Base {
   
    // Method
    public void display()
    {
        System.out.println("Base display()");
    }
}
 
// Class 2
// Main class
class Derived extends Base {
   
    // Overriding method as already up in above class
    @Override public void display(int x)
    {
        // Print statement when this method is called
        System.out.println("Derived display(int )");
    }
 
    // Method 2
    // Main driver method
    public static void main(String args[])
    {
        // Creating object of this class inside main()
        Derived obj = new Derived();
 
        // Calling display() method inside main()
        obj.display();
    }
}


Java
// Java Program to Demonstrate Type Annotation
 
// Importing required classes
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
 
// Using target annotation to annotate a type
@Target(ElementType.TYPE_USE)
 
// Declaring a simple type annotation
@interface TypeAnnoDemo{}
 
// Main class
public class GFG {
   
    // Main driver method
    public static void main(String[] args) {
 
        // Annotating the type of a string
        @TypeAnnoDemo String string = "I am annotated with a type annotation";
        System.out.println(string);
        abc();
    }
 
    // Annotating return type of a function
    static @TypeAnnoDemo int abc() {
       
        System.out.println("This function's  return type is annotated");
       
        return 0;
    }
}


Java
// Java Program to Demonstrate a Repeatable Annotation
 
// Importing required classes
import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
 
// Make Words annotation repeatable
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(MyRepeatedAnnos.class)
@interface Words
{
    String word() default "Hello";
    int value() default 0;
}
 
// Create container annotation
@Retention(RetentionPolicy.RUNTIME)
@interface MyRepeatedAnnos
{
    Words[] value();
}
public class Main {
 
    // Repeat Words on newMethod
    @Words(word = "First", value = 1)
    @Words(word = "Second", value = 2)
    public static void newMethod()
    {
        Main obj = new Main();
 
        try {
            Class c = obj.getClass();
 
            // Obtain the annotation for newMethod
            Method m = c.getMethod("newMethod");
 
            // Display the repeated annotation
            Annotation anno
                = m.getAnnotation(MyRepeatedAnnos.class);
            System.out.println(anno);
        }
        catch (NoSuchMethodException e) {
            System.out.println(e);
        }
    }
    public static void main(String[] args) { newMethod(); }
}


Java
public class DeprecatedTest
{
    @Deprecated
    public void Display()
    {
        System.out.println("Deprecatedtest display()");
    }
 
    public static void main(String args[])
    {
        DeprecatedTest d1 = new DeprecatedTest();
        d1.Display();
    }
}


Java
// Java Program to Illustrate Override Annotation
 
// Class 1
class Base
{
     public void Display()
     {
         System.out.println("Base display()");
     }
      
     public static void main(String args[])
     {
         Base t1 = new Derived();
         t1.Display();
     }    
}
 
// Class 2
// Extending above class
class Derived extends Base
{
     @Override
     public void Display()
     {
         System.out.println("Derived display()");
     }
}


Java
// Java Program to illustrate SuppressWarnings Annotation
 
// Class 1
class DeprecatedTest
{
    @Deprecated
    public void Display()
    {
        System.out.println("Deprecatedtest display()");
    }
}
 
// Class 2
public class SuppressWarningTest
{
    // If we comment below annotation, program generates
    // warning
    @SuppressWarnings({"checked", "deprecation"})
    public static void main(String args[])
    {
        DeprecatedTest d1 = new DeprecatedTest();
        d1.Display();
    }
}


Java
// Java Program to Demonstrate User-defined Annotations
 
package source;
 
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
 
// User-defined annotation
@Documented
@Retention(RetentionPolicy.RUNTIME)
@ interface TestAnnotation
{
    String Developer() default "Rahul";
    String Expirydate();
} // will be retained at runtime
 
// Driver class that uses @TestAnnotation
public class Test
{
    @TestAnnotation(Developer="Rahul", Expirydate="01-10-2020")
    void fun1()
    {
        System.out.println("Test method 1");
    }
 
    @TestAnnotation(Developer="Anil", Expirydate="01-10-2021")
    void fun2()
    {
        System.out.println("Test method 2");
    }
     
    public static void main(String args[])
    {
        System.out.println("Hello");
    }
}


输出:

10: error: method does not override or implement
    a method from a supertype

如果我们删除参数 (int x) 或删除 @override,程序编译得很好。

注释的类别

列出的注释大致分为 5 类:

  1. 标记注释
  2. 单值注解
  3. 完整注释
  4. 类型注释
  5. 重复注释

让我们讨论一下,如果需要,我们将在需要的地方附加代码。

第 1 类:标记注释

唯一的目的是标记一个声明。这些注释不包含任何成员,也不包含任何数据。因此,它作为注释的存在就足够了。由于标记接口不包含任何成员,因此只需确定它是否存在就足够了。 @Override是标记注释的一个示例。

例子

@TestAnnotation()

类别 2:单值注释

这些注释只包含一个成员,并允许以简写形式指定成员的值。我们只需要在应用注解时指定该成员的值,不需要指定成员的名称。然而,为了使用这个速记,成员的名字必须是一个值。

例子

@TestAnnotation(“testing”);

第 3 类:完整注释

这些注释由多个数据成员、名称、值、对组成。

例子

@TestAnnotation(owner=”Rahul”, value=”Class Geeks”)

第 4 类:类型注释

这些注释可以应用于任何使用类型的地方。例如,我们可以注释方法的返回类型。这些是用@Target注释声明的。

例子

Java

// Java Program to Demonstrate Type Annotation
 
// Importing required classes
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
 
// Using target annotation to annotate a type
@Target(ElementType.TYPE_USE)
 
// Declaring a simple type annotation
@interface TypeAnnoDemo{}
 
// Main class
public class GFG {
   
    // Main driver method
    public static void main(String[] args) {
 
        // Annotating the type of a string
        @TypeAnnoDemo String string = "I am annotated with a type annotation";
        System.out.println(string);
        abc();
    }
 
    // Annotating return type of a function
    static @TypeAnnoDemo int abc() {
       
        System.out.println("This function's  return type is annotated");
       
        return 0;
    }
}
输出:
I am annotated with a type annotation
This function's  return type is annotated

第 5 类:重复注释

这些是可以多次应用于单个项目的注释。要使注解可重复,必须使用@Repeatable注解进行注解,该注解在Java.lang.annotation包中定义。它的值字段指定可重复注释的容器类型容器被指定为一个注解,其值字段是一个可重复注解类型的数组。因此,要创建可重复的注解,首先要创建容器注解,然后将注解类型指定为@Repeatable 注解的参数。

例子:

Java

// Java Program to Demonstrate a Repeatable Annotation
 
// Importing required classes
import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
 
// Make Words annotation repeatable
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(MyRepeatedAnnos.class)
@interface Words
{
    String word() default "Hello";
    int value() default 0;
}
 
// Create container annotation
@Retention(RetentionPolicy.RUNTIME)
@interface MyRepeatedAnnos
{
    Words[] value();
}
public class Main {
 
    // Repeat Words on newMethod
    @Words(word = "First", value = 1)
    @Words(word = "Second", value = 2)
    public static void newMethod()
    {
        Main obj = new Main();
 
        try {
            Class c = obj.getClass();
 
            // Obtain the annotation for newMethod
            Method m = c.getMethod("newMethod");
 
            // Display the repeated annotation
            Annotation anno
                = m.getAnnotation(MyRepeatedAnnos.class);
            System.out.println(anno);
        }
        catch (NoSuchMethodException e) {
            System.out.println(e);
        }
    }
    public static void main(String[] args) { newMethod(); }
}
输出:
@MyRepeatedAnnos(value={@Words(value=1, word="First"), @Words(value=2, word="Second")})

预定义/标准注释

正如我们在层次图中看到的那样, Java普遍定义了七个内置注释。

  • 从Java.lang.annotation导入了四个:@Retention、@ Documented@Target@Inherited
  • Java.lang 中包含三个: @Deprecated、@ Override 和@SuppressWarnings

注释 1: @Deprecated

  • 它是一个标记注释。它表示声明已过时并已被更新的形式取代。
  • 当元素已被弃用时,应使用 Javadoc @deprecated 标记。
  • @deprecated 标签用于文档,@Deprecated 注释用于运行时反射。
  • 当两者一起使用时,@deprecated 标签的优先级高于 @Deprecated 注解。

例子:

Java

public class DeprecatedTest
{
    @Deprecated
    public void Display()
    {
        System.out.println("Deprecatedtest display()");
    }
 
    public static void main(String args[])
    {
        DeprecatedTest d1 = new DeprecatedTest();
        d1.Display();
    }
}
输出
Deprecatedtest display()

注释 2:@Override

它是一个标记注释,只能用于方法。使用@Override注解的方法必须覆盖超类中的方法。如果没有,将导致编译时错误(例如,请参阅this)。它用于确保超类方法实际上被覆盖,而不是简单地重载。

例子

Java

// Java Program to Illustrate Override Annotation
 
// Class 1
class Base
{
     public void Display()
     {
         System.out.println("Base display()");
     }
      
     public static void main(String args[])
     {
         Base t1 = new Derived();
         t1.Display();
     }    
}
 
// Class 2
// Extending above class
class Derived extends Base
{
     @Override
     public void Display()
     {
         System.out.println("Derived display()");
     }
}
输出
Derived display()

注释 3:@SuppressWarnings

它用于通知编译器抑制指定的编译器警告。要抑制的警告由名称以字符串形式指定。这种类型的注释可以应用于任何类型的声明。

Java将警告分为两类。它们已被弃用未经检查。当遗留代码与使用泛型的代码接口时,会生成任何未经检查的警告。

例子:

Java

// Java Program to illustrate SuppressWarnings Annotation
 
// Class 1
class DeprecatedTest
{
    @Deprecated
    public void Display()
    {
        System.out.println("Deprecatedtest display()");
    }
}
 
// Class 2
public class SuppressWarningTest
{
    // If we comment below annotation, program generates
    // warning
    @SuppressWarnings({"checked", "deprecation"})
    public static void main(String args[])
    {
        DeprecatedTest d1 = new DeprecatedTest();
        d1.Display();
    }
}
输出
Deprecatedtest display()

注释 4:@Documented

它是一个标记界面,告诉工具要记录注释。注释不包含在“Javadoc”注释中。在代码中使用@Documented 注释使Javadoc 等工具能够对其进行处理,并将注释类型信息包含在生成的文档中。

注释 5:@Target

它被设计为仅用作另一个注释的注释。 @Target接受一个参数,该参数必须是ElementType枚举中的常量。此参数指定可以应用注释的声明类型。下面显示了常量以及它们对应的声明类型。

Target ConstantAnnotations Can Be Applied To
ANNOTATION_TYPEAnother annotation
CONSTRUCTORConstructor
FIELDField
LOCAL_VARIABLELocal variable
METHODMethod
PACKAGEPackage
PARAMETERParameter
TYPEClass, Interface, or enumeration

我们可以在@Target注释中指定这些值中的一个或多个。要指定多个值,我们必须在大括号分隔的列表中指定它们。例如,要指定注解仅适用于字段和局部变量,您可以使用此@Target 注解: @Target({ElementType.FIELD, ElementType.LOCAL_VARIABLE}) @Retention Annotation它确定注解保留在何处以及保留多长时间. @Retention 注释可以具有的 3 个值:

  • SOURCE:注解将保留在源代码级别并被编译器忽略。
  • CLASS:注解将在编译时保留并被 JVM 忽略。
  • RUNTIME:这些将在运行时保留。

注释 6: @Inherited

@Inherited 是一个标记注解,只能用于注解声明。它只影响将在类声明中使用的注释。 @Inherited使超类的注解被子类继承。因此,当向子类发出对特定注释的请求时,如果子类中不存在该注释,则检查其超类。如果该注解存在于超类中,并且如果它使用@Inherited 进行注解,则该注解将被返回。

注解7:用户自定义(Custom)

用户定义的注释可用于注释程序元素,即变量、构造函数、方法等。这些注释可以在元素(构造函数、方法、类等)声明之前应用。

语法:声明

[Access Specifier] @interface
{         
   DataType () [default value];
}

在实现用户定义的注释之前,请务必将这些特定点作为自定义注释的规则。

  1. AnnotationName是一个接口。
  2. 参数不应与方法声明相关联,并且throws子句不应与方法声明一起使用。
  3. 参数不会有空值,但可以有默认值。
  4. 默认值是可选的。
  5. 方法的返回类型应该是原始、枚举、字符串、类名或原始数组、枚举、字符串或类名类型。

例子:

Java

// Java Program to Demonstrate User-defined Annotations
 
package source;
 
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
 
// User-defined annotation
@Documented
@Retention(RetentionPolicy.RUNTIME)
@ interface TestAnnotation
{
    String Developer() default "Rahul";
    String Expirydate();
} // will be retained at runtime
 
// Driver class that uses @TestAnnotation
public class Test
{
    @TestAnnotation(Developer="Rahul", Expirydate="01-10-2020")
    void fun1()
    {
        System.out.println("Test method 1");
    }
 
    @TestAnnotation(Developer="Anil", Expirydate="01-10-2021")
    void fun2()
    {
        System.out.println("Test method 2");
    }
     
    public static void main(String args[])
    {
        System.out.println("Hello");
    }
}

输出:

Hello