簡體   English   中英

如果我需要序列化我應該使用具體的List(例如ArrayList)還是(Serializable)List?

[英]If I need serializable should i use concrete List (e.g. ArrayList) or (Serializable)List?

我們在辦公室進行了討論,無法理解哪種方法更好

我有一個類(SomeClass)和一些接收Serializable對象的方法。 簽名如下:

public void someMethod(Serializable serializableObject){
    ...
}

我需要從另一個類調用此方法,但我應該為它提供一些List作為事實參數。 有兩種不同的方法

1.可序列化

private SomeClass someClass;

public void doSomething() {
    List<String> al = new ArrayList<String>();

    al.add("text");

    someClass.someMethod((Serializable)al);
}

2. ArrayList

private SomeClass someClass;

public void doSomething() {
    ArrayList<String> al = new ArrayList<String>();

    al.add("text");

    someClass.someMethod(al);
}
  1. 第一個例子的好處是它堅持java的最佳實踐,它說:使用接口而不是具體實現引用類型和任何程序員,同時閱讀該源將理解我們不需要ArrayList的特殊行為。 並且我們需要它的唯一可行序列化行為是通過將其轉換為Serializable接口來添加此行為。 程序員可以簡單地將List的當前實現更改為其他一些可序列化的實現,例如LinkedList,對此元素沒有任何副作用,因為我們使用接口List作為它的引用類型。

  2. 第二個例子的好處是我們將ArrayList稱為類,它不僅具有List行為,還具有Seri​​alizable行為。 因此,如果有人查看此代碼並嘗試將ArrayList更改為List,則會收到編譯時錯誤,這會減少程序員理解其中發生的事情的時間

更新:我們無法更改someMethod簽名。 它來自第三方公司,我們不僅將它用於Serializable Lists,還用於Strings,Integers和其他一些Serializable對象

當您需要的只是接口提供的方法時,您應該使用接口。 (這是大多數情況)但是,如果您需要多個接口,則可以使用泛型,但最簡單的方法是使用具體類型。

最好定義ArrayList因為它結合了兩個接口 - List + Serializable 你需要在一個地方同時使用它們。

這並不重要,但並不是說使用接口應該更嚴格地應用於返回類型,而不是嚴格地應用於局部變量。

我會更改someMethod的簽名,以便它反映了方法的調用者所需的內容:

public class SomeClass {

    public <T extends List<? extends Serializable> & Serializable> void someMethod(T t) {

    }

    public static void main(String[] args) {
        SomeClass test = new SomeClass();
        test.someMethod(new ArrayList<String>());   //Works
        test.someMethod(new ArrayList<Image>());   //Compile time error, Image is not Serializable
        List<String> l = null;
        test.someMethod(l); //Compile time error
    }
}

someMethod的簽名現在表示你必須使用List東西來調用它,這是Serializable ,並包含可Serializable元素

1通常是正確的做法。 但是在這種情況下,我的意見是彎曲並將其聲明為ArrayList <>。 這樣可以避免轉換並保證某人無法將List的實現更改為不可序列化的實現。

你不能這樣做(1)因為你不能隨意改變List實現類型,這就是這樣做的全部想法。 您只能使用實現Serializable的List實現。 所以你可以在代碼中表達出來。

在這種情況下,我只會使用List,而不用擔心編譯器無法保證您的對象是可序列化的(如果您在其他地方做了正確的事情,很可能無論如何都是如此)。

請注意,以下類型的方法(接受Serializable參數)提供了錯誤的安全感,因為編譯器永遠不能保證需要序列化的整個對象圖實際上是可序列化的。

public void write(Serializable s);

考慮一個包含不可序列化對象的ArrayList(可序列化)。 簽名也可以是:

public void write(Object o);

然后你不必擔心所有無關的鑄造。

另外請注意,盡管您無法更改所使用的API的簽名,但您可以非常輕松地創建具有不同簽名的包裝API。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM