Serializable 对象中的静态方法调用

Static method call within a Serializable object

我和一位同事对特定场景存在分歧。

我们有一个 Serializable 对象,它有一个 toString() 方法。这个toString()是调用Apache的ReflectionToStringBuilder实现的。像这样:

public class Foo implements Serializable {
    // bunch of instance variables, getters and setters ...

    @Override
    public String toString() {
        return ReflectionToStringBuilder.toString(this);
    }
}

我们无法控制这些对象的传递方式。在我们的特定应用程序中,我们可能会通过 RMI 调用、HTTP POST(在写入 JSon 字符串后)、JMS 或其他协议来传递它们。

现在,JSon 字符串大小写无关紧要,因为它将以字符串形式发送,因此 toString() 方法的实现细节无关紧要。但是对于(某些)其他协议,我们期望序列化对象本身。

Serializable class 中的方法可以调用静态方法并且仍然(功能上)可序列化吗?它编译得很好,当然——但它仍然可以通过网络发送吗?如果接收服务在其 class 路径上没有静态方法的 class,它会反序列化失败吗?

是的,这行得通。 toString()从不被Java内置的序列化框架调用,所以它基本上可以为所欲为。

大多数时候,序列化对象只是逐个字段复制,没有调用对象的任何方法。 class 可以通过实现特殊方法来更改此默认行为(有关详细信息,请参阅 http://www.oracle.com/technetwork/articles/java/javaserial-1536170.html),但在您的示例中并非如此。因此,无论您的方法在做什么(不仅是 toString()),对于序列化都无关紧要。

现在第二个问题:如果 ReflectionToStringBuilder 不在 class 路径中会怎样?很简单:什么也没有发生。只要不使用 ReflectionToStringBuilder(即调用它的任何静态方法,或者您正在创建它的实例),就不会加载 class(或至少未链接),所以它是否存在并不重要。只有当你尝试实际使用那个 class 时,你才会得到 NoClassDefFoundError。所以反序列化你的对象会起作用,但如果你调用 toString(),你会得到一个异常。

您的示例非常适合序列化。

理论上 JSON Java 对象的表示只是序列化的另一种形式。所有序列化都是为了将​​对象 "state" 写入流并能够从流中读取该状态。它不关心对象具有的操作或它们是如何实现的,包括 toString 方法。 在这种情况下,Java 对象的状态由其实例变量表示,不包括对象 Class 定义。 当你读回你的 Foo 时,你的类路径中应该已经有 Foo.class 和 Apache 的 ReflectionToStringBuilder.class。