反序列化通用(但可序列化)类型

时间:2010-10-19 16:44:16

标签: java generics serialization

我想知道是否可以将泛型类型反序列化为该类型的实例。如果可能,Java是否考虑了泛型类型的自定义反序列化(如果有的话)?

就我而言,我正在尝试实现一个由包含元素的序列化形式的文件支持的List,并且需要从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),如果它有自定义的那个?

顺便说一句,我不想​​序列化整个列表。

2 个答案:

答案 0 :(得分:1)

Java泛型类型仅在编译期间和字节码中可见,并且一些数据也可通过反射API显示。但Java虚拟机对泛型类型一无所知(例如.net确实如此),因此List&lt; String&gt ;, List&lt; Object&gt;或List&lt; Integer&gt;或者只是List对于JVM来说都是一样的。你的'V'泛型类型参数只是Java的'Serializable',仅此而已,所以你的代码应该可行。它被称为类型擦除(.net泛型使用称为具体化的不同技术实现)。

答案 1 :(得分:1)

为什么这不起作用(原则上)?我没有测试过您的代码,但是当您使用FileBackedList<V>将对象序列化到文件中时,您可以再次正确地反序列化它们并使用不安全类型转换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);

所以继续做吧! : - )