了解暴力反射之前,先复习一下反射的基本知识。
一、什么是反射?
反射非常强大,它甚至能直接操作程序的私有属性。我们前面学习都有一个概念,被private封装的资源只能类内部访问,外部是不行的,但这个规定被反射赤裸裸的打破了。 反射就像一面镜子,它可以在运行时获取一个类的所有信息,可以获取到任何定义的信息(包括成员变量,成员方法,构造器等),并且可以操纵类的字段、方法、构造器等部分。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
所以暴力反射也是反射的一个特性,那么就来学习如何快乐的暴力突破(狗头~)。
二、什么是暴力反射?
一般来说,被private封装的资源只能被类内部访问,外部是不可以的,那如果我们就是要从外部去访问这个资源,应该怎么办?
带着这个疑问,我们在之前的反射知识的基础上,要学习一个方法。
setAccessable(boolean flag):如果boolean值为true,则取消访问检查。就是这样一个小小的代码,让我们突破了封装的局限,看来,被称为暴力反射还是很形象的。
所以,你想要访问类中的私有成员的时候,就要调用setAccessable() 方法,将其改为true ,这样,你就可以对类中的私有成员进行操作了。
代码举例:
定义一个Student类:
public class Student {
private String name;
int age;
public String address;
public Student() {
}
private Student(String name) {
this.name = name;
}
Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
private void function() {
System.out.println("function");
}
public void method1() {
System.out.println("method1");
}
public void method2(String s) {
System.out.println("method2" + s);
}
public String method3(String s, int i) {
return s + "," + i;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
?正常反射操作去给对象赋值。
public class Test04_2 {
public static void main(String[] args) throws NoSuchFieldException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<?> c = Class.forName("test02.Student");
Field address = c.getField("address");
Field name = c.getDeclaredField("name");
Field age = c.getDeclaredField("age");
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
address.set(obj,"西安");
name.set(obj,"林青霞");
age.set(obj,30);
System.out.println(obj);
}
}
?结果:报错
Exception in thread "main" java.lang.IllegalAccessException: Class test04.Test04_2 can not access a member of class test02.Student with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
at java.lang.reflect.Field.set(Field.java:761)
at test04.Test04_2.main(Test04_2.java:21)
调用setAccessable() 方法后:
public class Test04_2 {
public static void main(String[] args) throws NoSuchFieldException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<?> c = Class.forName("test02.Student");
Field address = c.getField("address");
Field name = c.getDeclaredField("name");
name.setAccessible(true);
Field age = c.getDeclaredField("age");
age.setAccessible(true);
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
address.set(obj, "西安");
name.set(obj, "林青霞");
age.set(obj, 30);
System.out.println(obj);
}
}
结果:
Student{name='林青霞', age=30, address='西安'}
|