2017-05-26 60 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。