Десериализация универсального (но Сериализуемого) типа - PullRequest
2 голосов
/ 19 октября 2010

Мне интересно, возможно ли десериализовать универсальный тип в экземпляр этого типа.Если это возможно, учитывает ли Java настраиваемую десериализацию универсального типа (если таковая имеется)?

В моем случае я пытаюсь реализовать List, который поддерживается файлом, который содержит сериализованныйформа элементов и требует создания экземпляра универсального типа из байта [], например:

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'
    }
}

Есть ли способ, которым этот тип вещи может работать?

Править: И если это сработает, я определенно собираюсь вызвать правильный readObject (ObjectInputStream) для типа V, если он имеет пользовательский?

Кстати, я не хочу сериализоватьвесь список.

Ответы [ 2 ]

1 голос
/ 27 ноября 2010

Почему это не сработает (в принципе)?Я не проверял ваш код, но когда вы используете этот самый FileBackedList<V> для сериализации ваших объектов в файл, вы можете снова правильно десериализовать их и вернуть их с использованием небезопасного приведения типа return (V) ....Причина этого заключается в следующем:

  • Даже если компилятор переведет V в Serializable, ваши конкретные объекты будут известны JVM как то, чем они являются, например, String, Integer или любой другой сериализуемыйобъект.Поэтому, когда вы сериализуете их в 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 голос
/ 09 ноября 2010

Универсальные типы Java видны только во время компиляции и в байт-коде, а некоторые данные также видны с помощью API отражения. Но виртуальная машина Java ничего не знает о универсальных типах (как, например, .net), поэтому List , List , List или просто List одинаковы для JVM. Ваш параметр универсального типа 'V' просто 'Сериализуемый' для Java, ничего более, поэтому ваш код должен работать. Это называется стиранием типов (обобщение .net реализовано с использованием другой техники, называемой reification).

...