Java----注解
前言:
从JDK5开始,Java增加对元数据的支持,也就是注解,注解与注释是有一定区别的,可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过注解开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。
1、什么是注解?
注解,可以看作是对 一个 类/方法 的一个扩展的模版,每个 类/方法 按照注解类中的规则,来为 类/方法 注解不同的参数,在用到的地方可以得到不同的 类/方法 中注解的各种参数与值
注解也就是Annotation,相信不少人也和我之前一样以为和注释和doc一样,是一段辅助性的文字,其实注解不是这样的。
从JDK5开始,java增加了对元数据(描述数据属性的信息)的支持。其实说白就是代码里的特殊标志,这些标志可以在编译,类加载,运行时被读取,并执行相应的处理,以便于其他工具补充信息或者进行部署。
作用在代码的注解是
- @Override-检查该方法是否是重载方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
- @Deprecated-标记过时方法。如果使用该方法,会报编译警告。
- @SuppressWarnings-指示编译器去忽略注释解中声明的警告。
作用在其他注解的注解(或者说元注解)是:
- @Retention-标识这个注释解怎么保存,是只在代码中,还是编入类文件中,或者是在运行时可以通过反射访问。
- @Documented-标记这些注解是否包含在用户文档中。
- @Target-标记这个注解应该是Java成员。
- @Inherited-标记这个注解是继承于该注解类(替代注解并没有继承于任何子类)
从Java 7开始,额外添加了3个注解:
- @SafeVarargs-Java 7开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
- @FunctionalInterface-Java 8开始支持,标识一个匿名函数或函数式接口。
- @Repeatable-Java 8开始支持,标识某注解可以在同一个声明上使用多次。
2、注解的使用
在使用注解时,在类名、方法名、域上直接用@+注解名即可。比如一个叫做MyAnnotation的注解:
1.类注解
在类A上添加@MyAnnotaion,即用MyAnnotation注解了类A。方法、域同理。
2.方法注解
用MyAnnotation注解了方法method()。
3.域注解。
用MyAnnotation注解了域a
3、自定义注解
java给我们提供了很多注解,有时我们需要自定义的注解。自定义注解和接口定义很像,比如我们定义一个叫做MyAnnotation的注解,像下面这样就定义好了。
public class Test2 {
private int age;
@MyAnnotation
public int getAge() {
return age;
}
}
//如何自定义注解呢? @interface 注解名,注意和 interface的区别
//除了这四个注解之外的所有注解,都叫做自定义注解!
@Target(ElementType.METHOD) //表示我这个注解,能够注解谁! 方法,字段,类
@Retention(RetentionPolicy.RUNTIME) //自定义注解我们都会使用 RetentionPolicy.RUNTIME 在运行时生效
@Documented //表示L可以在Javadoc中生成信息,没什么用!
@Inherited //表示子类可以继承父类的注解,一般也不用!
@interface MyAnnotation{
}
package com.kuang.annotation;
//自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class Test3 {
private int age;
@MyAnnotation3("aaa")
public int getAge() {
return age;
}
}
@Target(value={ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
String[] value(); //只有一个参数的一般名字叫做value, 可以省略!
}
@Target(value={ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
String name() default "";
int age() default 0;
int id() default -1; // String indexOf("abc") -1, 找不到,不存在
String[] schools();
}
4、反射(Reflaction)获取注解
JAVA中反射是动态获取信息以及动态调用对象方法的一种反射机制。JAVA的反射也是同理,我们需要获取类的信息时,就需要通过反射。注解的获取同样是通过反射。
- 获取注解有几个主要方法。
1.isAnnotationPresent()是否含有某个注解。
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {}
比如获取类A是否有注解MyAnnotation,有返回true,没有返回false。
boolean b = A.class.isAnnotationPresent(MyAnnotation.class);
2.getAnnotation()获取某种注解对象。
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}
比如获取类A的注解对象。获取到后我们就得到应用在类A时该注解的属性值。
MyAnnotation m = A.class.getAnnotation(MyAnnotation.class);
int id = m.id();
String msg = m.msg();
3.getAnnotations()获取应用的所有注解,结果存进数组。
public Annotation[] getAnnotations() {}
- 除了用类调用上述方法,我们还可以获取到该类中的方法和域去调用。
假如类A有方法method(),有域a。
public class A{
int a;
public void myMethod(){
//TODO
}
}
1.获取类方法,参数为方法名字符串。
Method method = A.class.getDeclaredMethod("myMethod");
2.获取域
Field field = A.class.getDeclaredField("a");