反射
单元测试方法:
是Java中最小的测试单元,使用灵活
语法要求:@Test+public +void +没有参数
执行方法:选中当前要测试方法名前的绿色小三角,成功执行会有绿色小对钩
反射普通属性及对象
创建字节码对象
根据字节码对象的方法(getFiled//属性 getMethod//方法 getCollection//构造方法),获取对应的方法
利用foreach循环进行遍历
利用反射创建目标类对象
/*反射创建对象的方案一:通过触发目标类的无参构造创建对象*/
Object o = clazz.newInstance();//newInstance:创建对象,默认无参
System.out.println(o);//Student{name='null', age=0}
/*反射创建对象的方案二:先获取指定的全参构造对象,再通过构造对象创建student对象*/
//获取指定的构造函数对象,注意要获取构造方法,需要指定参数,而且是字节码文件
Constructor<?> c = clazz.getConstructor(String.class, int.class);
//利用获取到的全参构造对象,创建目标类Student的对象
Object o2 = c.newInstance("lang", 8);
//打印创建好的学生类对象
System.out.println(o2);
反射私有属性及方法
获取字节码对象
根据字节码对象的(getDeclaredField//属性 getDeclaredMethod//方法名 getDeclaredConstructors//构造方法)
利用setAccessible方法将私有属性可见
save.setAccessible(true);
创建一个该属性/方法的对象
将属性加入进去,set方法//属性 invoke方法//方法
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
/*本类用于测试暴力反射*/
public class TestReflect2 {
/*通过暴力反射获取与操作属性*/
@Test
public void getFie() throws Exception {
//获取字节码对象
Class<?> clazz = Class.forName("cn.tedu.reflection.Person");
//通过字节码对象获取私有属性,注意需要传入属性名,确认要获取那个是私有属性
Field field = clazz.getDeclaredField("name");
// //根据获取到的属性对象,查看属性信息
// System.out.println(field);//直接打印获取到的字段对象
// System.out.println(field.getType());//class java.lang.String
// System.out.println(field.getType().getName());//java.lang.String
//设置属性值
//需要指定到底要给那个对象的name属性设置一个什么值
Object o = clazz.newInstance();//触发无参构造创建对象
//暴力反射需要设置私有资源可见
field.setAccessible(true);
//通过刚刚获取到的属性对象,给刚刚创建好的o对象设置属性值
//field是我们刚获取的name属性
//set(m,n)--m是给那个对象的name属性设置值,n是设置的具体值
field.set(o,"王五");
System.out.println(field.get(o));
}
@Test
public void getFie2() throws Exception {
Class<?> clazz = Person.class;
Field field = clazz.getDeclaredField("age");
field.setAccessible(true);
Object o = clazz.newInstance();
field.set(o,90);
System.out.println(field.get(o));
}
/*通过暴力反射获取与操作私有方法*/
@Test
public void getFunction2() throws Exception {
Class<?> clazz = new Person().getClass();
//通过字节码对象获取私有方法
/*getDeclareMethod(m,x,y,z...)
* m:要获取方法的名字
* x,y,z...:可变参数,指的是目标方法的参数个数
* x,y,z 传入的是参数对应的类型,而且这个类型也必须是字节码对象*/
Method save = clazz.getDeclaredMethod("save", int.class, String.class);
//私有属性设置权限,使私有可见
save.setAccessible(true);
Object o = clazz.newInstance();
/*invoke(o,x,y,z...)表示通过反射技术执行方法
o:要给那个对象执行方法
x,y,z...可变参数,之前获取的方法参数类型是什么,此处就穿对应个数的值*/
save.invoke(o,90,"狼");
}
/*巩固-通过暴力反射获取与操作私有方法*/
@Test
public void getFunction3() throws Exception{
Class<?> clazz = Class.forName("cn.tedu.reflection.Person");
Method update = clazz.getDeclaredMethod("add",boolean.class);
update.setAccessible(true);
Object o = clazz.newInstance();
update.invoke(o,true);
}
@Test
public void getFuction4() throws Exception {
Class<Person> clazz = Person.class;
Method method = clazz.getDeclaredMethod("add", boolean.class);
method.setAccessible(true);
Person person = clazz.newInstance();
method.invoke(person,true);
}
@Test
public void getObj() throws Exception {
Class<?> clazz = Student.class;
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
for (Constructor c :constructors) {
System.out.println("---------");
System.out.println(c.getName());
Class[] types = c.getParameterTypes();
System.out.println(Arrays.toString(types));
}
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
Object o = constructor.newInstance("张三", 33);
System.out.println(o);
}
}