通过反射破除类的封装性

大家都知道JAVA中为了保持类的封装性,往往用private修饰属性,然后public定义set和get方法;

下面看一段代码,首先定义一个Book类:

package pojo;

/**
 * Created by ZhuHao on 2018/10/8
 */
public class Book {
    private String title;
    private double price;
    public Book(){
    }
    public Book(String title,double price){
        this.title = title;
        this.price = price;
    }
    public void setTitle(String title){
        this.title = title;
    }
    public String getTitle(){
        return this.title;
    }
    public void setPrice(double price){
        this.price = price;
    }
    public double getPrice(){
        return this.price;
    }
}

然后编写一个类测试,该类通过反射获得Book类的实例后获得类的属性并尝试直接修改:

public class TestDemo {
    public static void main(String[] args) throws Exception{
        Class cls = Class.forName("pojo.Book");
        Object obj = cls.newInstance();
        Field titleField = cls.getDeclaredField("title");

        titleField.set(obj,"Java开发");
        System.out.println(titleField.get(obj));
    }
}

运行结果如下所示,可以看到报异常,显示测试类无法访问private属性:

Exception in thread "main" java.lang.IllegalAccessException: Class TestDemo can not access a member of class pojo.Book 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 TestDemo.main(TestDemo.java:18)

Process finished with exit code 1

然后我们在TestDemo类中加一句

titleField.setAccessible(true);

该方法属于AccessibleObject,而java.lang.reflect.Field是java.lang.reflect.AccessibleObject的子类,设为true后禁用了JAVA的权限控制检查,代码如下:

public class TestDemo {
    public static void main(String[] args) throws Exception{
        Class cls = Class.forName("pojo.Book");
        Object obj = cls.newInstance();
        Field titleField = cls.getDeclaredField("title");
        titleField.setAccessible(true);//取消封装
        titleField.set(obj,"Java开发");
        System.out.println(titleField.get(obj));
    }

}

运行后控制台输出:

Java开发

猜你喜欢

转载自blog.csdn.net/ecliiipse/article/details/82988774