java注解

Java注解

  • 注解概述
  • 内置的基本注解类型
  • 自定义注解类型
  • 对注解进行注解
  • 使用反射获取注解信息

注解概述

annotation。可以添加到程序的任何元素上,用来设置一些说明和解释,java开发和部署工具可以读取这些注释,并以某种形式处理这些注释,可生成其他java源文件、XML文档或要与包含注释的程序一起使用的其他构件。

元数据:描述数据的一种数据。

注解是代码中的特殊标记,可以再编译、类加载、运行时被读取,并执行响应的处理。

注解被用来为程序元素(类、方法、成员变量等)设置元数据,它不影响程序代码的执行,无论增加、删除注解程序的执行都不受任何的影响。

访问和处理注解的工具统称为:APT(Annotation Processing Tool)。

JDK内置的基本注解类型

采用@标记,后面根生注解类型名称,name = value的形式。

@SuppressWarnings(value={"unchecked"});

注解类型和注解的区别:注解类型是某一类型注解的定义,注解是某注解类型的具体实例。

重写Override

限定重写的方法,指明被注解的方法必须是重写超类中的方法,这个注解只能用于方法上。编译器在编译源代码时会检查用@Override标注的方法是否有重写父类的方法。

被Override注解的方法必须在父类中存在同样的方法,编译才能通过。

警告Deprecated

用来标记已过时的成员的注解类型,用来指明被注解的方法是一个过时的方法,不建议使用了。编译到Deprecated的方法的类,编译器会产生警告。

抑制警告SuppressWarnings

抑制编译器警告的注解类型,用来指明被注解的方法、边或类在编译时如果有警告信息,就阻止警告。

public class SuppressWarningsTest {
    public static void main() {
    	List list = new ArrayList();
        list.add("xx");
    }
}

编译这段代码会得到警告

注意:SuppressWarningsTest使用了未经检查或不安全的操作。
注意:要了解详细新,请使用-Xlint:unchecked重新编译

List类必须使用泛型才是安全的,才能进行类型检查。

两种方法不显示警告:

public class SuppressWarningsTest {
    public static void main() {
    	List<String> list = new ArrayList<String>();
        list.add("xx");
    }
}
public class SuppressWarningsTest {
    @SupressWarnings("unchecked")
    public static void main() {
    	List list = new ArrayList();
        list.add("xx");
    }
}

@SupressWarnings(value ={"unchecked", "deprecation"})表示要抑制未检查和已过时警告。

自定义注解类型

注解类型的定义和接口类型的定义差不多,知识在interface前面多加了一个"@"

public @interface MyAnnotation {
    String value(); //定义一个属性 也可以不定义
}
class User{
    @MyAnnotation("abc") //此处的abc若没有显示指定属性名,却指定了属性值,而恰好有名为value的属性名,则隐式将值赋给value属性,若果没有value属性,就会出现编译错误。
    public void method(){
        
    }
}

也可以给属性赋默认值。

enum Status {ACTIVE, INACTIVE};
public @interface MyAnnotation {
    String value(); //定义一个属性 也可以不定义
    Status status() default Status.ACTIVE;
}

也可以显示指定值。

对注解进行注解

对注解类型的注解。

目标Target

ElementType枚举类型。

public enum ElementType {
    Type,				//适用于类、接口、枚举
    FILED,				//适用于成员字段
    METHOD,				//适用于方法
    PARAMETER,			//适用于方法的参数
    CONSTRUCTOR,		//适用于构造方法
    LOCAL_VARIABLE,		//适用越局部变量
    ANNOTATION_TYPE,	//适用于注解类型
    PACAGE				//适用于包
}

使用Target时至少要提供这些枚举值中的一个,以指定该被注解的注解类型可以应用于程序上的哪些元素。

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
//表示自定义这个注解类型只能作用在构造方法和成员方法上
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
@interface MethodAnnotation {
    
}
@MethodAnnotation //作用在类上 -->编译出错
public class TargetTest {
    @MethodAnnotaion //作用在方法上 -->正确
    public void myMthod(){}
}

类型Retention

要读取程序中的注解信息,首先要把注解信息留在程序中,即保存在class文件中才能被读出来。

三种方式:

  • 编译器处理完,不保留注解到编译后的类文件中
  • 将注解保存在编译后的类文件中,但是在运行时忽略它
  • 将注解保存在编译后的类文件中,并再第一次加载类时读取它。

三种方式对应java.lang.annotation.RetentionPolicy枚举的3个值

public enum RetentionPolicy {
    SOURCE, //编译器处理完,不保留注解到编译后的类文件中
    CLASS, //将注解保存在编译后的类文件中,但是在运行时忽略它
    RUNTIME //将注解保存在编译后的类文件中,并再第一次加载类时读取它
}

@Retention(RetentionPolicy.SOURCE)
@interface My1{}
@interface My2{}
@Retention(RetentionPolicy.RUNTIME)
@interface My3{}


My1不爆粗你在class文件中,类似java代码中的//注释,在编译成字节码时会被过滤掉。

My2使用默认值CLASS将被保存在class文件中,但在运行时会被忽略,不能被反射读取。

My3可以再运行时通过反射来读取它的信息。

Override、SupressWarnings为SOURCE,Deprecated为RUNTIME。

文档Document

注解和文档有关。

定义为Document的注解必须设置为Retention的值为RUNTIME

@Document
@Retention(RetentionPolicy.RUNTIME)
@interface DocAnnotation {
    
}

继承Inherited

继承注解。

父类的注解默认不能被子类继承。

要想继承需要添加Inherited注解

利用反射获取注解信息

注解必须是RUNTIME的。

java.lang.relect.AnnotatedElement接口定义了四种反射读取注解信息。

  • public Annotation getAnnotation(Class annotationType):如果存在该元素的指定类型的注解,则返回这些注解,否则返回null
  • public Annotation[] getAnnotations():返回此元素上存在的所有注解
  • public Annotation[] getDeclaredAnnotations():返回存在于此元素上的所有注解
  • public boolean isAnnotationPresent(Class annotationType):如果指定类型的直接存在于此元素上则返回true否则返回false

java.lang.Class类和java.lang.reflect包中的Constructor、Filed、Method、Package类都实现了AnnotatonElement接口。

package Annotation;
import java.lang.annotation.*;
import java.lang.reflect.Method;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno {
    String value() default "无值";// 默认值

}

@MyAnno
class UserMyanno{
    @MyAnno("method")
    @Deprecated
    public void test() {

    }
}

public class MyAnnotation {
    public static void main(String[] args) throws SecurityException, NoSuchMethodException {
        //获取指定类注释类的Annotation实例
        Annotation anno1 = UserMyanno.class.getAnnotation(MyAnno.class);
        if (anno1 != null) {
            MyAnno myAnno = (MyAnno)anno1;
            System.out.println("类上的MyAnno注解:value="+myAnno.value());
        }
        //取的test()方法的对应Method实例
        Method method = UserMyanno.class.getMethod("test");
        Annotation[] annotations = method.getAnnotations();
        for (Annotation anno : annotations) {
            System.out.println("注解类型名为:"+anno.annotationType().getName());
        }
    }
}


原文地址:https://www.cnblogs.com/DengSchoo/p/12853291.html