注解与反射
注解与反射
- 注解 Annotation
- 什么是注解
- 注解分类
- 内置注解
- 元注解
- @Target
- @Retention
- @Documented
- @Inherited
- 自定义注解
- 示例
- 反射 Reflect
- 什么是反射
- 常用方法
- 获取Class类
- 获取实例
- 操作方法
- 操作属性
- 操作泛型
- 操作注解
注解 Annotation
什么是注解
说白了就是对程序的解释,其实跟注释是一个含义,但是注解可以被程序读取,进行后续处理。
注解分类
内置注解
JDK自带的注解,包括常见的@Override
(方法重写)、@Deprecated
(方法弃用)、 @SuperWarnings
(忽略警告) 等等。
元注解
修饰注解的注解,称之为元注解。
常用的元注解有以下几类。
@Target
注解可以修饰哪些元素。
ElementType | 作用域 |
---|---|
PACKAGE | 包 |
CONSTRUCTOR | 构造器 |
FIELD | 属性 |
LOCAL_VARIABLE | 局部变量 |
METHOD | 方法 |
PARAMETER | 参数 |
TYPE | 类、接口、注解、枚举 |
@Retention
指明该注解的生命周期
RetentionPolicy | 作用 |
---|---|
SOURCE | 在源文件中有效(即源文件保留) |
CLASS | 在class文件中有效(即class保留) |
RUNTIME | 在运行时有效(即运行时保留)注:为RUNTIME时可以被反射机制所读取 |
@Documented
使用此修饰的注解将会被 javadoc 工具提取成文档,使用此注解,其 @Retention
必须被设置为 RetentionPolicy.RUNTIME
。
@Inherited
使得注解具有继承性。
自定义注解
- 使用
@interface
关键词,自动继承了java.lang.annotation.Annotation
接口 - 返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)
- 可以通过default来声明参数的默认值
- 如果只有一个参数成员,一般参数名为value
示例
自定义注解
// 可作用于类、方法、字段
@Target({ ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnntation{
// 如果没有default,那么在使用这个注解时,必须传递这些参数
String name() default "";
int length() default 0;
}
实体类
// lombok的注解
@Data
@AllArgsConstructor
@NoArgsConstructor
@MyAnntation(name = "user",length = 10)
public class User {
@MyAnntation(name = "id",length = 32)
private String userId;
@MyAnntation(name = "userName", length = 50)
private String userName;
private String sex;
private String idCard;
private String note;
private String id;
@MyAnntation()
public void func(){
}
public List<String> func2(Map<String,Object> map,Integer i){
return null;
}
}
反射 Reflect
什么是反射
反射指的是程序在运行期间借助反射 API 取得任何类的内部信息,并通过这些内部信息去操作对应对象的内部属性和方法。
任何一个类,在第一次使用时,就会被 JVM 加载到堆内存的方法区中。JVM 加载类成功后,就会在方法区中产生一个对应的 Class 对象(一个类只要一个 Class 对象),这个 Class 对象包含被加载类的全部结构信息。
常用方法
获取Class类
// 方法一
Class c1 = Class.forName("com.xxx.User");
// 方法二
Class c2 = User.class;
// 方法三
User user = new User();
Class c3 = user.getClass();
// 获取类名
String name = c1.getName();
获取实例
// 通过无参构造获取实例对象
User u1 = (User) c1.newInstance();
// 如果没有无参构造,可以通过带参构造获取实例对象
Constructor con = c1.getDeclaredConstructor(String.class,String.class,String.class,String.class,String.class,String.class);
User u2 = (User) con.newInstance("no001","xzy","","","","");
操作方法
// 获取所有方法 只包含public的方法以及父类的public方法
Method[] mArr1 = c1.getMethods();
// 获取所有方法 包含私有方法
Method[] mArr2 = c1.getDeclaredMethods();
// 获取指定名称的方法
Method getId = c1.getDeclaredMethod("getId");
// 方法名称,参数类型
Method setId = c1.getDeclaredMethod("setId", String.class);
// 调用setId方法
// @Param 对象
// @Param 参数
setId.invoke(u1, "NO001");
String id = getId.invoke(u1);
操作属性
// 获取public属性
c1.getFields();
// 获取所有属性
c1.getDeclaredFields();
// 获取指定属性
Field userName = c1.getDeclaredField("userName");
// 加上这个访问权限即可,不加会报错 Class com.xxx.reflect.ReflectClass can not access a member of class com.xxx.pojo.User with modifiers "private"
userName.setAccessible(true);
userName.set(user,"xzy");
String name = (String) userName.get(user);
System.out.println(name);
操作泛型
// 先获取方法
Method method = c1.getDeclaredMethod("func2", Map.class,Integer.class);
// 获取方法参数类型 java.util.Map<java.lang.String, java.lang.Object> java.lang.Integer
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println(genericParameterType);
// 若属于参数化类型,则获取类型对象的数组,表示此类型的实际类型参数
if(genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
//打印下实际类型参数
System.err.println(actualTypeArgument);
}
}
}
操作注解
// 获取所有注解
Annotation[] arr = c1.getDeclaredAnnotations();
for (Annotation annotation : arr) {
System.out.println(annotation);
}
// 获取指定的注解
MyAnntation annotation = (MyAnntation) c1.getDeclaredAnnotation(MyAnntation.class);
// 输出注解的属性值
System.out.println(annotation.name());
System.out.println(annotation.length());
// 获取字段上的注解
Field userName = c1.getDeclaredField("userName");
MyAnntation fliedAnn = userName.getAnnotation(MyAnntation.class);
System.out.println(fliedAnn.name());
System.out.println(fliedAnn.length());
// 获取方法上的注解
Method f1 = c1.getDeclaredMethod("func");
MyAnntation fAnn = f1.getAnnotation(MyAnntation.class);
System.out.println(fAnn.name());
还没有评论,来说两句吧...