概念:反射就像一面镜子,它可以在运行时获取一个类的所有信息,可以获取到任何定义的信息(包括成员变量,成员方法,构造器等),并且可以操纵类的字段、方法、构造器等部分。
常用方法
获取包名 类名
clazz.getPackage().getName()//包名
clazz.getSimpleName()//类名
clazz.getName()//完整类名
获取成员变量定义信息
getFields()//获取所有公开的成员变量,包括继承变量
getDeclaredFields()//获取本类定义的成员变量,包括私有,但不包括继承的变量
getField(变量名)
getDeclaredField(变量名)
获取构造方法定义信息
getConstructor(参数类型列表)//获取公开的构造方法
getConstructors()//获取所有的公开的构造方法
getDeclaredConstructors()//获取所有的构造方法,包括私有
getDeclaredConstructor(int.class,String.class)
获取方法定义信息
getMethods()//获取所有可见的方法,包括继承的方法
getMethod(方法名,参数类型列表)
getDeclaredMethods()//获取本类定义的的方法,包括私有,不包括继承的方法
getDeclaredMethod(方法名,int.class,String.class)
反射新建实例
clazz.newInstance();//执行无参构造创建对象
clazz.newInstance(666,”海绵宝宝”);//执行含参构造创建对象
clazz.getConstructor(int.class,String.class)//获取构造方法
反射调用成员变量
clazz.getDeclaredField(变量名);//获取变量
clazz.setAccessible(true);//使私有成员允许访问
f.set(实例,值);//为指定实例的变量赋值,静态变量,第一参数给null
f.get(实例);//访问指定实例变量的值,静态变量,第一参数给null
反射调用成员方法
Method m = Clazz.getDeclaredMethod(方法名,参数类型列表);
m.setAccessible(true);//使私有方法允许被调用
m.invoke(实例,参数数据);//让指定实例来执行该方法
主体代码:
package cn.tedu.reflection;
//学习反射的物料类
public class Student {
private String name;
public int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void play(){
System.out.println("今天大结局,放学后我要写1w行代码");
}
public void eat(int n){
System.out.println("今天要吃"+n+"道好菜");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
获取字节码对象的3种方式:
package cn.tedu.reflection;
import org.junit.Test;
public class TestReflect {
@Test
public void getClazz() throws ClassNotFoundException {
Class<?> clazz1 = Class.forName("cn.tedu.reflection.Student");
Class<?> clazz2 = Student.class;
Class<?> clazz3 = new Student().getClass();
System.out.println(clazz1);
System.out.println(clazz2);
System.out.println(clazz3);
}
}
运行结果:
class cn.tedu.reflection.Student
class cn.tedu.reflection.Student
class cn.tedu.reflection.Student
package cn.tedu.reflection;
import org.junit.Test;
public class TestReflect {
@Test
public void getClazz() throws ClassNotFoundException {
//通过字节码对象获取student类的资源
Class<?> clazz1 = Class.forName("cn.tedu.reflection.Student");
System.out.println(clazz1);
//获取字节码对象对应的全路径名
System.out.println(clazz1.getName());
//获取字节码对象对应的类名
System.out.println(clazz1.getSimpleName());
//获取Student类对应的包对象
System.out.println(clazz1.getPackage());
//先获取Student类对应的包对象,再通过这个包对象获取包名
System.out.println(clazz1.getPackage().getName());
}
}
运行结果:
class cn.tedu.reflection.Student
cn.tedu.reflection.Student
Student
package cn.tedu.reflection
cn.tedu.reflection
通过触发目标类的无参构造和构造函数创建对象
@Test
public void getObject() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class<?> clazz = Class.forName("cn.tedu.reflection.Student");
Object o = clazz.newInstance();
System.out.println(o);
//获取目标类中指定的全参构造函数对象
Constructor<?> c = clazz.getConstructor(String.class,int.class);
//创建对象并赋值
Object o2 = c.newInstance("赵六", 6);
System.out.println(o2);
}
运行结果:
Student{name='null', age=0}
Student{name='赵六', age=6}
暴力反射:获取私有属性和方法
package cn.tedu.reflection;
//本类用于暴力反射的物料类
public class Person {
private String name;
private int age;
private void save(int n,String s){
System.out.println("save方法"+n+s);
}
private void update(){
System.out.println("update方法");
}
}
package cn.tedu.reflection;
import org.junit.Test;
import java.lang.reflect.Field;
//本类用于测试暴力反射
public class TestReflect2 {
//通过暴力反射获取与操作属性
@Test
public void GetFie2() throws Exception {
Class<?> clazz = Class.forName("cn.tedu.reflection.Person");
//获取指定的私有属性,方法参数传入的就是指定的属性的名字
Field field = clazz.getDeclaredField("name");
System.out.println(field);
//通过刚刚获取的属性对象,进一步查看属性的各种信息
System.out.println(field.getType());
System.out.println(field.getType().getName());
//设置属性的值
//需要指定是哪个对象的name属性设置值,所以创建对象
Object p1 = clazz.newInstance();
//暴力反射,需要设置私有私有可见的权限
field.setAccessible(true);
//通过字段对象给刚刚创建好的p1设置属性值
//field.set(o,n);o是指具体给那个对象的属性设置值,n是指具体的值是什么
field.set(p1,"海绵");
//field.get(p1);o是指具体查看哪个对象的name属性
System.out.println(field.get(p1));
}
//通过暴力反射获取与操作方法
@Test
public void getFuntion() throws Exception {
Class<?> clazz = Class.forName("cn.tedu.reflection.Person");
//获取指定的私有方法
//clazz.getDeclaredMethod(n,x,y,z....)n是获取的指定方法的方法名,xyz是指定方法的参数类型
Method method= clazz.getDeclaredMethod("save", int.class, String.class);
//暴力反射设置权限
method.setAccessible(true);
//创建persion对象
Object p3 = clazz.newInstance();
//invoke(o,x,y,z)通过反射执行方法o:是要给哪个对象执行上面获取的save(),xyz是执行save()时需要传入的参数
method.invoke(p3,999,"感冒灵");
}
}
运行结果:
private java.lang.String cn.tedu.reflection.Person.name
class java.lang.String
java.lang.String
海绵
save方法999感冒灵