2010-10-19 92 views
2

我想知道是否有可能將泛型類型反序列化爲該類型的一個實例。如果可能,Java是否考慮了泛型類型的自定義反序列化(如果有的話)?反序列化泛型(但可序列化)類型

在我的情況,我想實現由它包含的元素的序列化格式的文件支持的列表,並需要從一個byte []實例化一個泛型類型,如:

class FileBackedList<V extends Serializable> implements List<V> { 
    // ... 

    public V get(int index) { 
     byte[] value = readFromFile(index); 
     // ??????? 
     // I'm pretty certain this doesn't work 
     return (V)(new ObjectInputStream(new ByteArrayInputStream(value)).readObject()); 
    } 

    private byte[] readFromFile(int index) { 
     // read bytes at line 'index' 
    } 
} 

這種類型的東西可以工作嗎?

編輯:如果它確實工作,我肯定會調用類型V的正確的readObject(ObjectInputStream in),如果它有一個自定義的?

順便說一下,我不想序列化整個列表。

+4

你試過了嗎? – skaffman 2010-10-19 16:45:43

+0

只需修復編譯錯誤(實現'List'或擴展'ArrayList'並且'ByteArrayInputStream'沒有'readObject()'方法)並嘗試一下。 – BalusC 2010-10-19 16:47:34

+0

skaffman:不,因爲我還沒有序列化表單的文件。即使它可以工作,我想知道是否將使用默認的readObject(),或者如果定義了自定義的一個(現在編輯該問題以說明),將調用V的(通用類型)readObject。 BalusC:更正了那些現在實現List的拼寫錯誤,並添加了缺失的括號,以便調用OIS.readObject()。 – AshirusNW 2010-10-19 16:52:37

回答

1

爲什麼不這樣做(原則上)?我沒有測試過你的代碼,但是當你使用非常有效的FileBackedList<V>來將你的對象串入到文件中時,你可以再次正確地反序列化它們並使用不安全類型cast return (V) ...返回它們。原因如下:

  • 即使V被編譯器翻譯成Serializable,你的具體對象也是JVM所知道的,例如,字符串,整數或任何其他可序列化的對象。因此,當你在ObjectOutputStream上對它們進行序列化時,將存儲具體類型。
  • 當您從ObjectInputStream再次加載對象時,您將得到具有正確類型的相同對象(例如String,Integer或其他)。其實與V相同

因爲你從外界隱藏你的列表的實現,不安全的類型轉換將工作。示例:

FileBackedList<String> list = new FileBackedList<String>(); 

// This will probably serialise the String "abc" to your file 
list.add("abc"); 

// This will not work. <V> is always String for FileBackedList<String> 
list.add(Integer.valueOf(1)); 

// This will be type-safe. It can only be String because you bind V to String 
String abc = list.get(0); 

所以繼續做吧! :-)

1

Java泛型類型僅在編譯和字節碼期間可見,並且一些數據也可以通過反射API顯示。但是Java虛擬機對通用類型一無所知(比如.net),因此列表<字符串>,列表<對象>或列表<整數>或者僅列表對於JVM都是相同的。你的'V'泛型類型參數只是用於Java的'Serializable',沒有什麼更多的東西,所以你的代碼應該可以工作。它被稱爲類型擦除(.net泛型使用不同的技術稱爲實現)。