2010-10-19 1 views
2

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

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

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 in) для типа V, если он имеет пользовательский?

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

+4

Вы пробовали? – skaffman

+0

Просто исправьте ошибки компиляции (либо реализуйте «Список», либо расширьте «ArrayList», а также «ByteArrayInputStream» не имеет метода readObject() »и попробуйте сами. – BalusC

+0

skaffman: Нет, поскольку у меня нет файла с сериализованной формой. Даже если это сработает, я хочу знать, будет ли использоваться readObject() по умолчанию, или будет вызван readObject V (общий тип), если он определил пользовательский (теперь отредактирован вопрос, чтобы уточнить). BalusC: Исправлено то опечатки теперь реализует List и добавляет отсутствующую скобку, поэтому вызывается OIS.readObject(). – AshirusNW

ответ

1

Почему бы не работать (в принципе)? Я не тестировал ваш код, но когда вы используете этот очень FileBackedList<V>, чтобы сериализовать ваши объекты в файл, вы можете правильно их десериализовать и вернуть их с помощью небезопасного типа cast 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

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

Смежные вопросы