文章目录
一、java已有的标注注解举例
- @Override 重写
- @Overlode重载
- @Deprecated 建议不使用旧API
- @SupressWarnings 屏蔽警告信息
- …
二、java的四个元注解
1、@Retention – 定义该注解的生命周期,有如下几种参数选择
- RetentionPolicy.RUNTIME : 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。
- RetentionPolicy.SOURCE : 在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。
- RetentionPolicy.CLASS : 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式
2、@Target – 表示该注解用于什么地方。默认值为任何元素,表示该注解用于什么地方。可用的ElementType 参数包括
- ElementType.CONSTRUCTOR: 用于描述构造器
- ElementType.FIELD: 成员变量、对象、属性(包括enum实例)
- ElementType.LOCAL_VARIABLE: 用于描述局部变量
- ElementType.METHOD: 用于描述方法
- ElementType.PACKAGE: 用于描述包
- ElementType.PARAMETER: 用于描述参数
- ElementType.TYPE: 用于描述类、接口(包括注解类型) 或enum声明
3、@Documented – 表示将注解信息添加在java 文档中
4、@Inherited – 允许子类继承父类的注解
- @Inherited 元注解是一个标记注解,@Inherited 阐述了某个被标注的类型是被继承的。
- 如果一个使用了@Inherited 修饰的注解annotation 类型被用于一个class,则这个annotation 将被用于该class 的子类。
三、java怎么自定义注解(实例)
3.1 第一步、声明自定义注解类
package com.gaunyi.batteryonline.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义注解类声明
*/
@Target(value= {ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})//用于声明当前注解类的作用范围分别为:类、方法、属性
@Retention(value = RetentionPolicy.RUNTIME)//运行时保留该注解,可以通过反射读取注解信息
public @interface MyAnnotationDefinition {
/*定义注解里面的参数信息*/
String name();
String value();
String path();
}
3.2 第二步、在需要的地方使用/调用注解类
在类或方法或属性上方使用注解类
package com.gaunyi.batteryonline.annotation;
/**
* Created by S0111 on 2019/8/20.
* 自定义注解类使用
*/
@MyAnnotationDefinition(name="类名称",value="类值",path="类路径")
public class MyAnnotationUse {
@MyAnnotationDefinition(name="属性名",value="属性值",path="属性路径")
private String name;
@MyAnnotationDefinition(name="年龄",value="18",path="/user2")
private String age;
@MyAnnotationDefinition(name="方法名",value="方法值",path="方法访问路径")
public String testAnno(){
return "successs!!!";
}
@MyAnnotationDefinition(name="方法名1",value="方法值1",path="方法访问路径1")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
3.3 第三步、读取注解类信息(测试)
一般是通过反射读取注解信息,注解内容与对应的类、方法、属性对应。
package com.gaunyi.batteryonline.annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 自定义注解类测试
*/
public class MyAnnotationTest {
public static void main(String[] args) throws Exception{
//通过MyAnnotationUse类的全路径和类名信息得到MyAnnotationUse类
Class clazz = Class.forName("com.gaunyi.batteryonline.annotation.MyAnnotationUse");
//获取MyAnnotationUse类上方的@MyAnnotationDefinition注解信息
MyAnnotationDefinition classAnno =(MyAnnotationDefinition)clazz.getAnnotation(MyAnnotationDefinition.class);
System.out.println( classAnno.name()+"---"+classAnno.value()+"---"+classAnno.path());
//获取所有方法注解信息 ps:这里需要使用 isAnnotationPresent 判断方法上是否使用了注解
Method[] allMethods = clazz.getDeclaredMethods();
for(int i=0;i<allMethods.length;i++){
//A.isAnnotationPresent(B.class)意思是:注释B是否在此A上。如果在则返回true;不在则返回false。
if(allMethods[i].isAnnotationPresent(MyAnnotationDefinition.class)) {
//获取某method上的@MyAnnotationDefinition注解信息
MyAnnotationDefinition methodAnno = allMethods[i].getAnnotation(MyAnnotationDefinition.class);
System.out.println("遍历:当前方法名为:"+allMethods[i].getName()+" 的注解信息:---"+methodAnno.name() + "---" + methodAnno.value() + "---" + methodAnno.path());
}
}
//获取指定方法注解信息
Method methodTest = clazz.getDeclaredMethod("testAnno");
MyAnnotationDefinition methodAnnotest = methodTest.getAnnotation(MyAnnotationDefinition.class);
System.out.println( methodAnnotest.name()+"---"+methodAnnotest.value()+"---"+methodAnnotest.path());
//获取属性注解信息
Field nameField = clazz.getDeclaredField("name");
MyAnnotationDefinition attrAnno = nameField.getAnnotation(MyAnnotationDefinition.class);
System.out.println( attrAnno.name()+"---"+attrAnno.value()+"---"+attrAnno.path());
}
}