反射
反射即 从配置文件中读取类的信息,java代码运行时才知道实际的类
package ref;
import java.io.IOException;
import java.util.Properties;
public class Test2 {
private static Properties properties;
static {
properties = new Properties();
try {
properties.load(Test2.class.getResourceAsStream("../bean.properties"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws ClassNotFoundException {
String bean = properties.getProperty("bean");
Class clazz = Class.forName(bean);
Constructor constructor = clazz.getConstructor();
Object object = constructor.newInstance();
}
}
步骤都是1.得到类对象,2.获得构造器,3.构造实例。
注解
作为标识符,通过反射实现功能。例如自动创建实例并赋值。
1.自定义注解
package ref;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyValue {
String value();
}
package ref;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyComponent {
}
自定义注解需要添加原注解:
@Retention:注解生效时期
@Target:注解生效范围(给类/属性加)
2.给类加上自定义注解
package ref;
@MyComponent
public class Dog {
@MyValue("大黄")
private String name;
@MyValue("2")
private int age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
3.通过注解完成对应的功能
package ref;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws Exception {
Class<Dog> dogClass = Dog.class;
MyComponent annotation = dogClass.getAnnotation(MyComponent.class);
if(annotation!=null){
Constructor<Dog> constructor = dogClass.getConstructor();
Dog dog = constructor.newInstance();
Field[] declaredFields = dogClass.getDeclaredFields();
for (Field declar:declaredFields){
MyValue valueAnnotation = declar.getAnnotation(MyValue.class);
if(valueAnnotation!=null){
declar.setAccessible(true);
if(declar.getType().getName().equals("int")){
Integer val = Integer.valueOf(valueAnnotation.value());
declar.set(dog,val);
}else{
declar.set(dog,valueAnnotation.value());
}
}
}
System.out.println(dog);
}
}
}
第一步仍是获取类对象。
通过调用getAnnotation方法判断是否有相对应的注解。
仍旧是通过获取构造器去生成对象实例。
这里需要注意的是,给属性赋值时,由于时private修饰,故需要做暴力反射:
declar.setAccessible(true);
4.通过有参构造器构造实例
对象代码如下:
package ref;
@MyComponent
public class Dog {
public Dog(String name) {
this.name = name;
}
@MyValue("大黄")
private String name;
@MyValue("2")
private int age;
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
那么在获取构造器时,需要指明是哪一个参数类型的构造器,并且在实例化的时候,也需要传入相对应的参数
如:
Class<Dog> dogClass = Dog.class;
MyComponent annotation = dogClass.getAnnotation(MyComponent.class);
if(annotation!=null){
Constructor<Dog> constructor = dogClass.getConstructor(String.class);
System.out.println("123");
Dog aa = constructor.newInstance("aa");
System.out.println(aa);
}
参考视频:
反射