2010-10-19 91 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泛型使用不同的技术称为实现)。