反射
1.什么是反射
Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。
2.为什么使用反射
反射是为了解决在运行期,对某个实例一无所知的情况下,调用其方法或属性。
3.如何获取一个类的反射类实例
// 方式1: 使用全类名
Class c1 = Class.forName("全类名");
// 方式2: 类名.class 以 Student 的类为例
Class c2 = Student.class;
// 方式3: 使用类对象获取
Class c3 = student.getClass();
4.Class类中常用的方法
package com.lyl.annotation;
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,ElementType.METHOD,ElementType.FIELD})
public @interface MyAnnotation {
String value();
}
package com.lyl.entity;
import com.lyl.annotation.MyAnnotation;
@MyAnnotation("lyl")
public class Student {
private String name;
private Integer age;
}
public class Test {
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
// 1.根据反射类获取类的实例 newInstance()
Class c1 = Student.class;
Student student = (Student) c1.newInstance();
System.out.println(student);
// 2.根据反射类获取类上的注解 getAnnotation(注解名.class)
MyAnnotation annotation = c1.getAnnotation(MyAnnotation.class);
System.out.println(annotation.value());
}
}
5.获取Method方法类对象
getDeclaredMethods(): 得到本类中所有的方法。
getDeclaredMethod("方法名",参数类型):获取本类中指定的方法对象
getMethods():获取本类以及父辈类中public修饰的方法。
getMethod("方法名",参数类型):获取本类以及父辈类中指定public修饰的方法。
// 1.得到本类中定义的所有Method类对象 getDeclaredMethods()
Class c1 = Student.class;
// 得到本类中定义的所有Method类对象
Method[] declaredMethods = aClass.getDeclaredMethods();
// 遍历所有的Method类对象
for(Method m :declaredMethods){
System.out.println(m);
}
// 2.获取本类中指定的Method类对象 getDeclaredMethod(方法名,...[参数类型的反射类实例])
Method m1 = c1.getDeclaredMethod("fun",Integer.class);
// 3.获取本类以及父类中所以public修饰的Method类对象
Method[] methods = c1.getMethods();
// 遍历所有的Method类对象
for(Method m :methods){
System.out.println(m);
}
// 4.获取本类以及父类中指定的public修饰的Method类对象
Method m2 = c1.getMethod("equals", Object.class);
System.out.println(m2);
6.Method类对象中常用的方法
// invoke("反射类的实例对象",...[参数类型的反射类实例])
// 例子
// 1.首先获取类的反射实例
Class c1 = Class.forName("全类名");
// 2.使用反射创建类的实例
Object o = c1.newInstance();
// 3.获取指定的 Method 类实例
Method m = c1.getMethod(方法名,...[参数类型的反射类实例]);
// 4.执行方法,返回方法执行的结果
Object result = m.invoke(o,...方法参数);
7.获取Field属性类对象
getDeclaredFields() 获取本类中所有的属性类对象
getDeclaredField(String name) 获取本类中所有的属性类对象
getFields() 获取所有本类和父类中 public 修饰的属性的属性类对象
getField(String name) 获取指定本类和父类中 public 修饰的属性的属性类对象
// 实例
// 1.首先获取类的反射类实例
Class c1 = 类名.class;
// 2.通过反射类创建类的实例
类名 实例名 = (类名) c1.newInstance();
// 3.获取指定属性的属性类实例
Field 属性名 = c1.getDeclaredField("属性名");
8.Field类中常用的方法
set(Object对象,值):为属性赋值
getName():获取属性名
getAnnotation():获取属性上的注解对象
// 1.为属性赋值 set(Object,值)
// 2.获取属性名 getName()
// 3.获取属性上的注解对象 getAnnotation()
// 实例
// 1.获取反射类的实例
Class c1 = 类名.class;
// 2.获取所有属性的属性类实例
Field[] fields = c1.getDeclaredFields();
// 3.遍历所有的属性类实例
for(Field field : fields){
// 输出所有的属性名
System.out.println(declaredField.getName());
// 获取每个属性对象上的注解对象
注解名 注解实例名 = field.getAnnotation(注解名.class);
类型名 变量名 = 注解实例名.value();
// 输出注解中的值
System.out.println(变量名);
}
// 4.为属性赋值
// 使用反射类生成类的实例
Object o = c1.newInstance();
// 获取指定属性的属性类实例
Field field = c1.getDeclaredField("属性名")
// 为实例中的属性赋值
field.set(o,属性值);
9.暴力反射
对于属性和方法中的私有字段,当使用反射获取后无法直接访问,需要在使用之前开启访问允许 ,使用方式如下:
属性类实例.setAccessible(true);
方法类实例.setAccessible(true);
属性类实例.setAccessible(true);
方法类实例.setAccessible(true);
10.反射综合案例
在properties属性文件中指定类的路径,通过反射完成类对象的创建以及类中属性的赋值
public class Test{
public static void main(String[] args) throws Exception {
//1.加载属性文件
InputStream resourceAsStream = Test.class.getClassLoader().getResourceAsStream("xxx.properties");
//2.通过属性类Properties
Properties properties=new Properties();
properties.load(resourceAsStream);
//3.属性类读取属性文件中指定的key的值
String className = properties.getProperty("className");
//4. 根据类路径得到反射对象
Class<?> aClass = Class.forName(className);
//5. 根据反射类创建类对象
Object o = aClass.newInstance();
System.out.println(o);
//6.为属性赋值
Field[] declaredFields = aClass.getDeclaredFields();
for(Field field:declaredFields){
field.setAccessible(true);
field.set(o,new Random().nextInt(1000)+"");
}
System.out.println(o);
}
}
xxx.properties
className=com.lyl.entity.people
com.lyl.entity.people
public class People{
private String name;
private String sex;
}