注解
注解(Annotation),也叫元数据。一种代码级别的说明。(JDK1.5后)。
与类、接口、枚举是在同一个层次。可以声明在包、类、(属性)字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
作用:
编写文档:通过代码里标识的注解生成文档 --> 生成文档doc文档
代码分析:通过代码里标识的注解对代码进行分析 --> 使用反射
编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查 --> Override
为了代码简洁、利于扩展和维护。
JDK内置注解
@Override:检测被该注解标注的方法是否是继承自父类(或接口)的 @Deprecated:该注解标注的内容,表示已过时 @SuppressWarnings:压制警告 1.deprecation:使用了不赞成使用的类或方法时的警告(使用@Deprecated使得编译器产生的警告)==>该方法已经过时了 2.unchecked:执行了未检查转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型; 关闭编译器警告。 3.fallthrough:当 Switch 程序块直接通往下一种情况而没有 Break 时的警告; 4.path:在类路径、源文件路径等中有不存在的路径时的警告; ==>FileNotFoundException 5.serial:当在可序列化的类上缺少 serialVersionUID 定义时的警告; 6.finally:任何 finally 子句不能正常完成时的警告; 7.all:关于以上所有情况的警告。
自定义注解
格式:
元注解 public @interface 注解名称{ 属性列表 }
注解的本质是一个 接口 。还接口默认继承了 Annotation 接口。
jvm运行时会自动帮我们创建它的实现类。
执行 javap 类名,进行反编译:
public interface MyAnno extends java.lang.annotation.Annotation {}
元注解
用于描述注解的注解
@Target:描述注解能过作用的位置 ElementType的取值: TYPE:可以作用于类上 METHOD:可以作用于方法上 FIELD:可以作用于成员变量上 @Retention:被保留的阶段 @Retention(RetentionPolicy.RUNTIME) --> 会保留到class字节码文件中,并被JVM读取到。运行时可以通过反射获得。 SOURCE:注解仅存在于源码中,在class字节码文件中不包含。 CLASS:默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得。 生命周期:SOURCE < CLASS < RUNTIME。 一般如果需要在运行时区动态获取注解信息,只能用RUNTIME。 如果要在编译时做一些预处理操作,比如生成一些辅助代码(如ButterKnife),用CLASS。 如果只是做一些检查性的操作,则可选用SOURCE。 @Documented:描述注解是否被抽取到api文档中 @Inherited:描述注解是否被子类继承
@Target的源码:
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Target { ElementType[] value(); }
ElemetType.java 源码
public enum ElementType { /** Class, interface (including annotation type), or enum declaration */ TYPE, /** Field declaration (includes enum constants) */ FIELD, /** Method declaration */ METHOD, /** Formal parameter declaration */ PARAMETER, /** Constructor declaration */ CONSTRUCTOR, /** Local variable declaration */ LOCAL_VARIABLE, /** Annotation type declaration */ ANNOTATION_TYPE, /** Package declaration */ PACKAGE, /** * Type parameter declaration * * @since 1.8 */ TYPE_PARAMETER, /** * Use of a type * * @since 1.8 */ TYPE_USE }
TYPE, 接口、类、枚举、注解
FIELD, 字段,枚举常量
METHOD, 方法
PARAMETER, 方法参数
CONSTRUCTOR, 构造函数
LOCAL_VARIABLE, 局部变量
ANNOTATION_TYPE, 注解
PACKAGE, 包
自定义注解&属性定义
属性:注解中的抽象方法。
属性的返回值,即抽象方法的返回值:
基本数据类型
枚举
注解
以上类型的数组
定义了属性,需要在使用时给属性赋值:
1、如果定义属性时,用default 给属性默认初始化值,则使用注解时,可以不进行属性的赋值。
String name() default "payn";
2、如果只有一个属性需要赋值,并属性的名称为value,则value可省略。
3、数组赋值时,值使用{}包裹。如果数组中只有一个值,{}可省略。
自定义注解实现反射功能:
注解类 Pro:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Pro { String className(); //代表了一套规范 String methodName(); String name() default "payn"; }
Demo01
public class Demo01 { public void show(){ System.out.println("demo01...show..."); } }
ReflectTest
@Pro(className = "com.itheima.anno01.Demo01",methodName = "show") public class ReflectTest { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException { //前提:不改变任何该类的任何代码,可以创建任意类的对象,执行任意方法。 //获取该类的字节码文件对象 Class<ReflectTest> reflectTestClass = ReflectTest.class; //获取上边的注解对象 //其实就是在内存中生成了一个该注解接口的子类实现对象 /* public class ProImpl implements Pro{ public String className(){ return "cn.itcast.annotation.Demo1"; } public String methodName(){ return "show"; } } */ Pro an = reflectTestClass.getAnnotation(Pro.class);//获取指定的注解 // System.out.println(an); //@com.itheima.anno01.Pro(className=com.itheima.anno01.Demo01, methodName=show) //获取注解对象中定义的抽象方法,获取返回值。 String className = an.className(); String methodName = an.methodName(); //加载Demo01类进内存 Class cls = Class.forName(className); Object obj = cls.newInstance(); Method method = cls.getMethod(methodName); //执行Demo01中的show方法 method.invoke(obj); } }

浙公网安备 33010602011771号