2017-05-26 59 views
0

一位同事和我对特定场景有不同意见。Serializable对象内的静态方法调用

我们有一个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类中的方法是否可以调用静态方法,并且仍然可以(功能上)可序列化?它编译得很好,当然 - 但它可以通过电线发送吗?如果接收服务的类路径中没有静态方法的类,它是否会失败反序列化?

+3

如何测试它?当通过线路发送对象时,序列化了什么,类的字节码(接收器已经在其类路径中),还是对象的状态(接收者不知道)? –

+1

接收服务如何获得类而不是静态方法的类? (实际上是问)。我认为,无论您如何在服务之间共享Serializable类(无论它们是否都获取库,或者是否重复了每个服务中的类),都不会在代码的类路径中存在任何外部库甚至编译? – Ishnark

+0

很好的描述可以在[Java静态序列化规则?](https:// stackoverflow。com/questions/6429462/java-static-serialization-rules) –

回答

1

是的,这将起作用。 Java内置的序列化框架永远不会调用toString(),所以它基本上可以做任何想要的事情。

大多数情况下,序列化对象只是逐个字段复制,没有任何对象被调用的方法。一个类可以通过实现特殊的方法来改变这种默认行为(详见http://www.oracle.com/technetwork/articles/java/javaserial-1536170.html),但在你的例子中情况并非如此。所以无论你的方法在做什么(不仅仅是toString()),它对于序列化并不重要。

现在到第二个问题:如果ReflectionToStringBuilder不在类路径中会发生什么?很简单:没有任何反应。只要ReflectionToStringBuilder没有被使用(即它的任何静态方法被调用,或者你正在创建它的一个实例),那个类没有被加载(或者至少没有被链接),所以不管它是否存在都没关系或不。只有当您尝试实际使用该课程时,才会获得NoClassDefFoundError。所以反序列化你的对象将会起作用,但是如果你打电话给toString(),你会得到一个异常。

1

你的例子对序列化来说是完全正确的。

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