Java 注解

  • 注解

    Java注解允许我们将元数据信息添加到源代码中,尽管它们不是程序本身的一部分。 注解是从JDK 5中添加到Java的。注解对其注解的代码的操作没有直接影响(即,它不影响程序的执行)。在本教程中,我们将涵盖以下主题:
    • 注解的用法
    • 如何应用注解
    • Java中可用的预定义注解类型以及如何创建自定义注解
  • 注解的用途是什么?

    1)编译器指令:Java中提供了三个内置注解(@Deprecated,@Override和@SuppressWarnings),可用于向编译器提供某些指令。 例如,@Override注解用于指示编译器已注解的方法将覆盖该方法。本文的下一部分将讨论更多有关这些内置注解的示例。
    2)编译时指令:注解可以向编译器提供编译时指令,软件构建工具可以将其进一步用于生成代码,XML文件等。
    3)运行时指令:我们可以定义在运行时可用的注解,我们可以使用java反射对其进行访问,并且可以在运行时向程序提供指令。 我们将在同一篇文章的稍后部分中借助示例进行讨论。
  • 注解基础

    注解始终以符号@开头,后跟注解名称。 符号@指示编译器这是一个注解。例如@Override 这里的@符号表示这是一个注解,而Override是此注解的名称。
    在哪里可以使用注解?
    注解可以应用于类,接口,方法和字段(属性)。 例如,下面的注解将应用于方法。
    @Override
    void myMethod() { 
        //Do something 
    }
    下一节将说明此注解的确切功能,但要简要说明,它是指示编译器myMethod()是重写方法,它正在重写超类的方法(myMethod())。
  • Java内置注解

    Java 有三个内置注解
    • @Override
    • @Deprecated
    • @SuppressWarnings
    1) @Override:
    在子类中重写方法时,我们应使用此注解标记该方法。 这使代码易于阅读,并避免了维护问题,例如:在更改父类的方法签名时,必须在子类(使用此注解的地方)中更改签名,否则编译器会抛出编译错误。 如果您未使用此注解,则很难跟踪。
    public class MyParentClass {
    
        public void justaMethod() {
            System.out.println("Parent class method");
        }
    }
    
    
    public class MyChildClass extends MyParentClass {
    
        @Override
        public void justaMethod() {
            System.out.println("Child class method");
        }
    }
    我相信这个例子是不言自明的。
    2) @Deprecated
    @Deprecated注解指示已弃用已标记的元素(类,方法或字段属性),并且不应再使用。 每当程序使用已被@Deprecated注解标记的方法,类或字段时,编译器就会生成警告。 不推荐使用元素时,还应使用Javadoc @deprecated标记对其进行记录,如以下示例所示。 使用@Deprecated和@deprecated记录大小写差异。 @deprecated用于文档。
    /**
     * @deprecated
     * reason for why it was deprecated
     */
    @Deprecated
    public void anyMethodHere(){
        // Do something
    }
    现在,只要任何程序使用此方法,编译器都会生成警告。
    3) @SuppressWarnings
    该注解指示编译器忽略特定的警告。 例如,在下面的代码中,我正在调用一个不赞成使用的方法(假设方法deprecatedMethod()用@Deprecated注解进行了标记),因此编译器应生成警告,但是我使用的是@SuppressWarnings注解,它将告诉编译器不在显示警告。
    @SuppressWarnings("deprecation")
        void myMethod() {
            myObject.deprecatedMethod();
    }
  • 创建自定义注解

    • 注解是使用@interface创建的,后跟注解名称,如以下示例所示。
    • 注解也可以包含元素。 它们看起来像方法。 例如,在下面的代码中,我们有四个元素。 我们不应该为这些元素提供实现。
    • 所有注解都扩展了java.lang.annotation.Annotation接口。 注解不能包含任何extends子句。
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
     
    @Documented
    @Target(ElementType.METHOD)
    @Inherited
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyCustomAnnotation{
        int studentAge() default 18;
        String studentName();
        String stuAddress();
        String stuStream() default "CSE";
    }
    注意:使用注解时,可以跳过创建注解时设置了默认值的所有元素。 例如,如果我将上述注解应用于一个类,则可以这样进行:
    @MyCustomAnnotation(
        studentName="Chaitanya",
        stuAddress="Agra, India"
    )
    public class MyClass {
    ...
    }
    如您所见,我们没有为studentAge和stuStream元素提供任何值,因为设置这些元素的值是可选的(默认值已在注解定义中设置,但是如果您愿意,可以在使用注解时分配新值 就像我们对其他元素所做的一样)。 但是,在使用注解时,我们必须提供其他元素的值(未设置默认值的元素)。
    注意:我们还可以在注解中包含数组元素。 这是我们如何使用它们
    注解定义:
    @interface MyCustomAnnotation {
        int      count();
        String[] books();
    }
    使用:
    @MyCustomAnnotation(
        count=3,
        books={"C++", "Java"}
    )
    public class MyClass {
    
    }
    让我们再次回到主题:在自定义注解示例中,我们使用了以下四个注解:@Documented,@Target,@Inherited和@Retention。 让我们详细讨论它们。
    @Documented
    @Documented注解指示使用此注解的元素应由JavaDoc记录。 例如:
    java.lang.annotation.Documented
    @Documented
    public @interface MyCustomAnnotation {
      //Annotation body
    }
    @MyCustomAnnotation
    public class MyClass { 
         //Class body
    }
    在为类MyClass生成Javadoc时,注解@MyCustomAnnotation将包含在其中。
    @Target
    它指定了我们可以在哪里使用注解。 例如:在下面的代码中,我们将目标类型定义为METHOD,这意味着下面的注解只能在方法上使用。
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Target;
    
    @Target({ElementType.METHOD})
    public @interface MyCustomAnnotation {
    
    }
    public class MyClass {
       @MyCustomAnnotation
       public void myMethod()
       {
           //Doing something
       }
    }
    注意
    • 1)如果未定义任何目标类型,则意味着可以将注解应用于任何元素。
    • 2)除了ElementType.METHOD,注解可以具有以下可能的Target值。
    • ElementType.METHOD
    • ElementType.PACKAGE
    • ElementType.PARAMETER
    • ElementType.TYPE
    • ElementType.ANNOTATION_TYPE
    • ElementType.CONSTRUCTOR
    • ElementType.LOCAL_VARIABLE
    • ElementType.FIELD
    @Inherited
    @Inherited注解表示一个类中使用的自定义注解应由其所有子类继承。 例如:
    java.lang.annotation.Inherited
    
    @Inherited
    public @interface MyCustomAnnotation {
    
    }
    @MyCustomAnnotation
    public class MyParentClass { 
      ... 
    }
    public class MyChildClass extends MyParentClass { 
       ... 
    }
    在这里,MyParentClass类使用的是@MyCustomAnnotation注解,该注解带有@inherited注解。 这意味着子类MyChildClass继承了@MyCustomAnnotation注解。
    @Retention
    它指示带有注解类型的注解将保留多长时间。
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    
    @Retention(RetentionPolicy.RUNTIME)
    @interface MyCustomAnnotation {
        
    }
    在这里,我们使用了RetentionPolicy.RUNTIME。 还有两个其他选择。 让我们看看它们是什么意思:
    • RetentionPolicy.RUNTIME:注解应该在运行时可用,以便通过Java反射进行检查。
    • RetentionPolicy.CLASS:注解将位于.class文件中,但在运行时将不可用。
    • RetentionPolicy.SOURCE:注解将在程序的源代码中可用,而不是在.class文件中,也不在运行时可用。