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。
我和一位同事对特定场景存在分歧。
我们有一个 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。