为什么允许通过反射访问Java私有字段?

时间:2009-08-06 15:13:28

标签: java reflection private-members

考虑这个例子:

import java.lang.reflect.Field;

public class Test {

    public static void main(String[] args) {
        C c = new C();
        try {
            Field f = C.class.getDeclaredField("a");
            f.setAccessible(true);
            Integer i = (Integer)f.get(c);
            System.out.println(i);
        } catch (Exception e) {}
    }
}

class C {
    private Integer a =6;
}

允许您通过反射访问类的私有字段似乎不合逻辑。为什么有这样的功能?允许这种访问是不是“危险”?

7 个答案:

答案 0 :(得分:58)

Private旨在防止意外滥用,而不是作为安全机制。如果您选择绕过它,那么您可以自担风险并假设您知道自己在做什么。

答案 1 :(得分:22)

安全管理器实际上检查了getDeclaredField()setAccessible(),并且在不允许您的代码执行此操作时将抛出异常。通常情况下,您不会注意到它,因为Java代码通常在没有安全管理器的情况下运行。

一个重要的例外是Applet,它总是与安全管理器一起运行。

答案 2 :(得分:10)

是的,它并不好,但它确实允许Java序列化等框架工作。

  

在反射对象中设置可访问标志允许具有足够权限的复杂应用程序(例如Java对象序列化或其他持久性机制)以通常禁止的方式操作对象。

我相信可以通过SecurityManager

禁用该功能

http://javabeans.asia/2008/10/12/how_to_set_securitymanager_and_java_security_policy_programmatically.html

答案 3 :(得分:8)

反思很危险。周期。

为了安全性稍微增加,限制真正危险系统的效用有什么意义?

此外,自动序列化需要能够“吸取大脑”的能力;在这种情况下,忽略访问修饰符是必要的。

答案 4 :(得分:4)

Reflection是一个完整的API,用于获取内部类。私人会员和所有人。

如果您不信任正在运行的代码(applet等),则可以阻止代码完全使用反射。有关详细信息,请参阅this Stack Overflow question

答案 5 :(得分:3)

来自:http://java.sun.com/docs/books/tutorial/reflect/

  

反射通常由程序使用,这些程序需要能够检查或修改在Java虚拟机中运行的应用程序的运行时行为。

这是一个让一个人破坏一些规则的工具,一个人可以把它扔到他的脚上或正确使用它。

答案 6 :(得分:3)

来自description of the java.lang.reflect包:

  

此包中的类,以及   java.lang.Class适应   调试器等应用程序   口译员,对象检查员,班级   浏览器和Object等服务   需要的序列化和JavaBeans   访问公共成员   目标对象(基于其运行时)   类)或由a声明的成员   给定的课程。

Reflection提供了一种通过类和对象之间的常规交互通常无法获得的方法来访问类的信息的机制。其中之一是允许从外部类和对象访问私有字段。

是的,反射一般来说确实很危险,因为它可以暴露类和对象的内部。

但是,它也是一个非常强大的工具,可用于检查类和对象的内部,这是其他标准方法无法访问的。