反射爆破创建实例
假设现在有这样一个实体类
class User{ private int age=10; private String name="杨宸"; public User(){ //无参 public } public User(String name){//public的有参构造器 this.name=name; } private User(int age,String name){//私有的有参构造 this.age = age; this.name = name; } @Override public String toString() { return "User{" + "age=" + age + ", name='" + name + '\'' + '}'; } }
里面有public无参构造器 public有参构造器 和一个私有的有参构造器,对于创建一个实例来说,我们可以使用这三种构造器的任意一种
对于public无参构造器来说
public class ReflecCreateInstance { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { //1.先获取到User类的Class对象 Class<?> userClass = Class.forName("Reflection.User"); //2.通过public的无参构造器创建实例 Object o = userClass.newInstance(); System.out.println(o); } }
运行结果
对于public有参构造来说
public class ReflecCreateInstance { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { //1.先获取到User类的Class对象 Class<?> userClass = Class.forName("Reflection.User"); //3.通过public的有参构造器创建实例 //3.1先得到对应的构造器 Constructor<?> constructor = userClass.getConstructor(String.class); //3.2创建实例,并传入参数 Object hsp = constructor.newInstance("hsp"); System.out.println("hsp="+hsp); } }
运行结果:
那么问题来了,如果对于私有的构造器来说我们难道可以用同样的方法来创建实例吗
我们实验一下
public class ReflecCreateInstance { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { //4.通过非public的有参构造器创建实例 //4.1得到private的构造器对象 Constructor<?> constructor1 = userClass.getDeclaredConstructor(int.class, String.class); //4.2创建实例 Object user2 = constructor1.newInstance(100, "张三丰"); System.out.println(user2); } }
运行结果
可以看出来虽然我们获得了这个私有的构造器,但却因为私有的原因,没有 办法来给它注入属性,实现实例的创建
那么怎么样来打破这种僵持的局面呢
我们可以在创建实例的时候将获得的私有构造器调用该方法,这个方法可以将我们的私有爆破掉,直接调用该构造器,就好比一个炸弹一样,将我们私有的锁炸开,这也就时你我们叫爆破的原因
反射爆破操作属性
假设我们现在有一个实体类
class Student{ public int age; private static String name; public Student(){//构造器 } @Override public String toString() { return "Student{" + "age=" + age +",name="+name+ '}'; } }
操作共有属性
public class ReflecAccessProperty { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException { //1.得到Student类对应的 Class对象 Class<?> stuClass = Class.forName("Reflection.Student"); //2.创建对象 Object o = stuClass.newInstance();//o的运行类型就是Student System.out.println(o.getClass()); //3.使用反射得到age,属性对象 Field age = stuClass.getField("age"); age.set(o,88); System.out.println(o); System.out.println(age.get(o));//得到age属性的值 } }
运行结果
操作私有属性
public class ReflecAccessProperty { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException { //1.得到Student类对应的 Class对象 Class<?> stuClass = Class.forName("Reflection.Student"); //4.使用反射操作name属性 Field name = stuClass.getDeclaredField("name"); //对name 进行爆破 name.setAccessible(true); name.set(null,"杨宸"); System.out.println(o); System.out.println(name.get(null));//获取属性值,要求name是static System.out.println(name.get(o));//获取属性值 } }
运行结果
反射爆破操作方法
假设现在有一个实体类
class Boss{//类 public int age; private static String name; public Boss(){//构造器 } private static String say(int n,String s,char c){ return n + " "+s+" "+c; } public void hi(String s){//普通public方法 System.out.println("hi"+s); } }
操作共有方法
public class ReflectAccessMethod { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException { //1.得到Boss类对应的Class对象 Class<?> bossCls = Class.forName("Reflection.Boss"); //创建对象 Object o = bossCls.newInstance(); //调用public的hi方法 Method hi = bossCls.getMethod("hi",String.class); //Method hi = bossCls.getDeclaredMethod("hi"); //调用 hi.invoke(o, "杨宸"); } }
运行结果
操作私有方法
public class ReflectAccessMethod { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException { //调用private static方法 //4.1得到say方法对象 Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class); //4.2因为say方法时private,所以需要爆破,原理和前面讲的构造器和属性一样 say.setAccessible(true); System.out.println(say.invoke(o,100,"张三",'男')); } }
运行结果