注解和反射-补充
本文章基于B站UP主 楠哥教你学Java 视频教程《注解反射的原理,一节课把你教会》进行整理记录,仅用于个人学习/交流使用
视频地址:注解反射的原理,一节课把你教会
反射
在程序运行期间动态创建对象
动态创建对象
动态
编写代码/编译的过程
,不知道
要创建的是哪个对象,只有在运行期间
才知道
要创建的对象是谁
暴力反射,通过反射机制强行赋值
案例:读取配置文件,创建反射对象
配置文件:
bean.properties
bean=com.lut.demo02.Dog
实体类:
com/lut/demo02/Dog.java
public class Dog {
private Integer id;
private String name;
@Override
public String toString() {
return "Dog{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
测试类:
public class Test {
private static Properties properties;
static {
try {
properties=new Properties();
properties.load(Test.class.getClassLoader().getResourceAsStream("bean.properties"));
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
String bean=properties.getProperty("bean");
Class clazz=Class.forName(bean);
Constructor constructor=clazz.getConstructor(null);
Dog mydog = (Dog) constructor.newInstance(null);
System.out.println(mydog);
}
}
输出结果:
Dog{id=null, name='null'}
注解
注解是结合反射
来运行,注解只是相当于一个标识
,不做具体的操作,具体操作是由反射来完成
的。
案例:自定义注解(功能:实现对属性的赋值),并利用反射完成注解的功能
注解:
@interface MyComponent
/**
* 自定义注解,加在类上,第一层判断
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyComponent {
}
@interface MyComponent
/**
* 自定义反射,用于给 属性赋值
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public@interface MyComponent {
String value();
}
实体类:
/**
* 其中MyComponent,MyValue 为自定义注解
*/
@MyComponent
public class Dog {
@MyValue("1")
private Integer id;
@MyValue("旺旺")
private String name;
@Override
public String toString() {
return "Dog{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
测试类:
package com.lut.demo01_ReflectionTest;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
/**
* @Author: GengKY
* @Date: 2021/8/20 9:31
* <p>
* 测试自定义反射
*/
public class Test {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//获取类对象
Class<Dog> dogClass = Dog.class;
//获取Mycomponent注解对象
MyComponent annotation = dogClass.getAnnotation(MyComponent.class);
//如果有 Mycomponent注解
if (annotation != null) {
System.out.println(dogClass + "添加了MyComponent注解");
//创建对象
Constructor<Dog> constructor = dogClass.getConstructor(null);
Dog dog = constructor.newInstance(null);
System.out.println("目前以获取dog对象"+dog);
//开始赋值,注意 getDeclaredFields() 与 getFields()的区别
Field[] declaredFields = dogClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
//获取value注解对象
MyValue valueAnnotation = declaredField.getAnnotation(MyValue.class);
if (valueAnnotation!=null){
//调用 value() 属性/方法
String value=valueAnnotation.value();
System.out.println(declaredField+"添加了MyValue注解,注解值是:"+value);
//暴力
declaredField.setAccessible(true);
//判断注解的类型
if (declaredField.getType().getName().equals("java.lang.Integer")){
Integer val=Integer.parseInt(value);
//用注解的方式,相当于 dog setid(val),这里 declaredField 是id
declaredField.set(dog,val);
}else {
declaredField.set(dog,value);
}
}
}
//完成之后,测试 dog
System.out.println("完成之后,测试 dog");
System.out.println(dog);
} else {
System.out.println(dogClass + "没有添加了MyComponent注解");
}
}
}
输出结果:
class com.lut.demo01_ReflectionTest.Dog添加了MyComponent注解
目前以获取dog对象Dog{id=null, name='null'}
private java.lang.Integer com.lut.demo01_ReflectionTest.Dog.id添加了MyValue注解,注解值是:1
private java.lang.String com.lut.demo01_ReflectionTest.Dog.name添加了MyValue注解,注解值是:旺旺
完成之后,测试 dog
Dog{id=1, name='旺旺'}