在java中序列化私有变量

在java中序列化私有变量,java,serialization,Java,Serialization,我有一个关于序列化的问题。如果我的类有私有变量,并且没有getter和setter,那么序列化API将如何读取这些变量的值 序列化API不担心私有变量。其目的是将对象转换为文件或其他类型存储中的二进制表示形式,以便以后重建 Java的序列化算法已经解释过了。不用担心,通过使用反射,任何人都可以访问用户的私有字段 这是一个示例。首先,访问权限是编译时功能。在运行时不控制访问 这可能会让您感到困惑,但请尝试执行以下操作: 创建类别A的两个版本: 1. 2. 现在编写一个调用新的A().foo()的类

我有一个关于序列化的问题。如果我的类有私有变量,并且没有getter和setter,那么序列化API将如何读取这些变量的值

序列化API不担心私有变量。其目的是将对象转换为文件或其他类型存储中的二进制表示形式,以便以后重建


Java的序列化算法已经解释过了。

不用担心,通过使用反射,任何人都可以访问用户的私有字段


这是一个示例。首先,访问权限是编译时功能。在运行时不控制访问

这可能会让您感到困惑,但请尝试执行以下操作: 创建类别A的两个版本:

1. 2. 现在编写一个调用新的A().foo()的类,并用类A的第一个版本编译它。然后将第二个版本放入类路径并运行应用程序。它会成功的

因此,不要担心访问权限:它们总是可以被绕过的

例如,如果使用反射从调用私有方法
foo()
,则必须获取该方法,然后调用
setAccessible(true)


如果我们可以从代码中访问私有方法,请确保JDK类可以做到这一点,即使它们是用java编写的。顺便说一句,据我所知,标准java序列化是作为本机代码实现的

默认序列化机制不关心成员变量的访问范围。换句话说,public、protected、package private和private变量都以相同的方式处理。实现细节可能会有所不同,但正如我所记得的,Sun JRE通过在本机(JNI)代码中实现大部分序列化来实现这一点,而本机(JNI)代码不强制执行访问权限。

但它确实需要读取值,对吗?而且API是用Java编写的,所以它必须有一种读取私有变量的方法。@SidCool:反射和序列化是在运行时执行的。封装更多的是一种设计。那么您认为如何在调试器中查看私有变量的值呢?声明私有变量实际上并不能以任何方式保护它。如果您可以访问它存储在的内存位置,或者从序列化文件中读取它,则仍然可以读取它。如果您不想发生这种情况(例如,使用密码),请使用
transient
关键字标记变量(这样它就不会被序列化),或者只在字段中以加密形式保存它(
java.security.*
有可用于此的类-谷歌无疑可以提供教程)。是的,您可以这样做。同样,您可以在调试器中执行此操作。我正在等待更好的答案。过一段时间我们会接受的。谢谢。这不影响封装吗?封装有什么问题吗?我不确定我是否理解这个问题。大多数序列化代码都是用Java编写的,但是字段访问确实使用了您所说的JNI。嗯?如果我没有完全错的话,第一部分就是错的。如果访问私有方法/字段,则在运行时会得到一个
IllegalAccessError
。这是JVM的要求(见第5.4.3节)。运行测试证实了这一点。
public class A {
    public foo() {
        System.out.println("hello");
    }
}
public class A {
    private foo() {
        System.out.println("hello");
    }
}
Method m = A.class.getMethod("foo",
null); m.setAccessible(true);
m.invoke(new A(), null);