注解概述
从
JDK5
开始,Java 增加对元数据
的支持,也就是注解,注解与注释是有一定区别的,可以把注解理解为代码里的特殊标记,可以在编译,类加载,运行
时被读取,并执行相应的处理。通过注解开发人员可以在 不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。应用于包、类型、构造方法、方法、成员变量、参数及本地变量
的声明语句中。
本质上是一个继承了Annotation
的特殊接口。
元注解
注解之上的注解,用来定义注解。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
元注解有六种:
@Target
:什么 地方使用该注解- ElementType.CONSTRUCTOR:用于描述构造器
- ElementType.FIELD:成员变量、对象、属性(包括enum实例)
- ElementType.LOCAL_VARIABLE:用于描述局部变量
- ElementType.METHOD:用于描述方法
- ElementType.PACKAGE:用于描述包
- ElementType.PARAMETER:用于描述参数
- ElementType.TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention
: 什么 时候使用该注解- RetentionPolicy.SOURCE:在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。
- RetentionPolicy.CLASS:在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。
- RetentionPolicy.RUNTIME :始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。
@Documented
:注解是否将包含在JavaDoc中@Inherited
:是否允许子类继承该注解@Repeatable
:1.8 新增,允许一个注解在一个元素上使用多次@Native
:1.8新增,修饰成员变量,表示这个变量可以被本地代码引用,常常被代码生成工具使用
JDK内置注解
@Override
:方法重写@Deprecated
:表示方法已经过时,方法上有横线,使用时会有警告。@SuppressWarnings
:表示关闭一些警告信息(通知java编译器忽略特定的编译警告)@SafeVarargs
: (jdk1.7更新) 表示:专门为抑制”堆污染”警告提供的。@FunctionalInterface
:(jdk1.8更新) 表示:用来指定某个接口必须是函数式接口,只能有一个需要实现的抽象方法,否则就会编译出错。
自定义注解
自定义注解规则
- 自定义注解需要添加元注解
- 所有 Annotation 定义类型为
@interface
,会自动继承java.lang.Annotaion
这个接口,并且不能再去继承别的类或是接口。 - 参数成员只能用 public 或默认(default) 这两个访问权修饰。
-
参数成员只能是
byte、short、char、int、long、float、double、boolean
八种基本数据类型和String、Enum、Class、annotations
等数据类型,以及这一些类型的数组. -
要获取类方法和字段的注解信息,必须通过 Java 的
反射
技术来获取 Annotation 对象,因为除此之外没有别的获取注解对象的方法 - 注解也可以没有定义成员,不过这样注解就没啥用了
创建自定义注解
需求:
创建一个注解,用于添加在字段上,可以起到给字段赋值的作用
步骤:
- 创建注解
import java.lang.annotation.*;
// 作用于字段
@Target(ElementType.FIELD)
// 运行期间有效
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationDemo {
// 类型 属性名 默认属性值
String value() default "龙傲天";
}
- 创建实体类
public class User {
@AnnotationDemo("李四")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
- 利用反射注解解析并赋值
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
public static Object getObject(String className) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
Class clazz = Class.forName(className);
Object obj = clazz.newInstance();
Field[] declaredFields = clazz.getDeclaredFields();
// 遍历所有字段
for (Field field : declaredFields) {
// 判断字段上是否添加有此注解
if (field.isAnnotationPresent(AnnotationDemo.class)){
// 获得该字段上存在的该注解对象
AnnotationDemo annotation = field.getAnnotation(AnnotationDemo.class);
// 获得字段的名称
String fieldName = field.getName();
// 得到修改该字段的方法
Method setMethod = clazz.getDeclaredMethod("set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1), String.class);
// 调用该方法,传入注解的值
setMethod.invoke(obj,annotation.value());
}
}
return obj;
}
}
- 测试
import java.lang.reflect.InvocationTargetException;
public class Method {
public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, InstantiationException {
User user = (User) Test.getObject("com.dong.User");
System.out.println(user);
}
}
- 输出
User{name='李四'}
Original: https://www.cnblogs.com/suwuji/p/16627633.html
Author: 苏无及
Title: 注解
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/613166/
转载文章受原作者版权保护。转载请注明原作者出处!