Почему java.lang.Void не сериализуем? - PullRequest
7 голосов
/ 11 февраля 2011

Возможно сериализовать примитив 'void' по умолчанию, почему объект 'Void' не расширяет Serializable?

Добавлен пример:

The RootImplementationбудет иметь ошибку компиляции, говорящую "Void не в пределах его границ", так как он не расширяет Serializable.Хотя бы 'someMethod' был объявлен с 'void', это не было бы проблемой.

public interface Root<R extends Serializable> extends Serializable {
  R someMethod();
}

public class RootImplementation implements Root<Void> {
  public Void someMethod() {
    return null;
  }
}

Ответы [ 8 ]

5 голосов
/ 11 февраля 2011

ОК, в ответ на ваш пример, нет, если вы изменили метод на void, он не будет работать, так как метод должен иметь тип возвращаемого значения (даже если Java теперь допускает ковариантные возвращаемые типы в переопределенных методах).Обсуждение void запутывает проблему.

То, что вы хотите сделать, это объявить параметр типа как «просто вернет ноль».Void, как правило, хороший выбор для этого, но для работы Void тип возвращаемого значения должен быть Object.Void не может реализовать каждый интерфейс в API только потому, что кто-то может захотеть использовать его для указания нулевого возврата параметра типа.

Есть три способа взглянуть на вашу проблему:

  1. Serializable - чрезмерно ограничительное объявление типа.Вы действительно должны использовать объект.Вам действительно нужно, чтобы он был Serializable?
  2. Вы можете просто объявить параметр типа как Serializable, и на практике вернуть null.Это не совсем означает, что вы возвращаете null каждый раз, но этого может быть достаточно.
  3. Вы можете объявить свой собственный класс с именем Null, который реализует Serializable, возможно, как статический вложенный класс интерфейса Root, ииспользуйте это как параметр типа в этом случае.Вы обнаружите, что создание собственного объекта Null не так уж редко, даже в стандартном JDK есть (частный).
4 голосов
/ 11 февраля 2011

Javadoc ясен:

Класс Void - это нереализуемый класс-заполнитель для хранения ссылки на объект Class, представляющий ключевое слово Java

Поскольку вы не можетеиспользуйте его, он не должен быть сериализуемым (кроме отражающего материала).


И для второго вопроса: void! = Void (если вы думаете о! = в не Java-выражении)

Да void - это ключевое слово, а Void - класс.

2 голосов
/ 11 февраля 2011

Я поставлю это здесь как comminity-wiki

Вы можете (де) сериализовать java.lang.Void b / c, вы можете инициализировать его только с нулевым значением. Java не волнует, реализует ли класс java.io.Serializable, если он null.

Результат кода

t1.VoidOut@19821f
t1.VoidOut@c17164
<Ч />
  public class VoidOut implements java.io.Serializable{
    int x=1;
    Void v = null;

    public static void main(String[] args) throws Throwable{
        VoidOut v = new VoidOut();
        System.out.println(v);
        ByteArrayOutputStream b =new ByteArrayOutputStream(256);
        ObjectOutputStream o = new ObjectOutputStream(b);
        o.writeObject(v);
        o.close();
        ObjectInputStream in =new ObjectInputStream(new ByteArrayInputStream(b.toByteArray()));
        System.out.println(in.readObject());        
    }
}
1 голос
/ 11 февраля 2011

Цитировать Javadocs:

Класс Void - это нереализуемый класс-заполнитель для хранения ссылки на объект Class, представляющий ключевое слово Java void.

Поскольку класс нереализуем, его нельзя десериализовать. Ergo не нуждается в поддержке сериализации.

0 голосов
/ 11 февраля 2011

Void предназначен только для того, чтобы показать, что метод может возвращать только null, к сожалению, нет способа напрямую объявить нулевой тип. Поскольку jvm Void является только обычным классом, расширяющим Object, и поэтому не может использоваться вместо других классов или интерфейсов, это делает Void для вашего примера бесполезным.

Поскольку ваш метод не возвращает ничего, кроме null, вы можете заменить Void на что-то вроде следующего:

public final SerializebaleVoid extends Object implements Serializeable{
    private SerializeableVoid(){}
}

Что касается вызова void примитива, void показывает отсутствие значения, метод, возвращающий void, не возвращает значение типа void, а буквально ничего не возвращает.

0 голосов
/ 11 февраля 2011

Другие объяснили, почему для типа, который никогда не может быть создан, не имеет смысла реализовывать Serializable и почему void не является примитивным или сериализуемым.

Чтобы обратиться к коду вваше редактирование, я думаю, вы должны просто изменить R extends Serializable ограничено просто R.Большинство общих типов, которые Serializable, не требуют, чтобы их параметры типа были Serializable ... они просто утверждают, что если вы поместите в них что-то, что не сериализуется, они также не будут сериализуемыми.Как правило, это хорошая практика, поскольку слишком сильная попытка обеспечить сериализуемость на уровне компилятора может вас укусить (как вы видите здесь).

0 голосов
/ 11 февраля 2011

Было бы полезно, если бы у вас было поле типа Void, которое действительно не имеет смысла.Вы также должны были бы фактически назначить ему экземпляр, который снова не имеет смысла.Пока вы этого не сделаете, вы можете сериализовать экземпляр класса, содержащий поле Void.Чтобы создать экземпляр Void, вам нужно использовать отражение, чтобы использовать приватный конструктор.

public class VoidSerializerDemo implements Serializable {
    private Void v;

    public static void main(String[] args) throws Exception {
        final VoidSerializerDemo instance = new VoidSerializerDemo();
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        final ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(instance);
        System.out.println("OK: null works");
        final Constructor<Void> constructor = Void.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        instance.v = constructor.newInstance();
        oos.reset();
        System.out.println("Going to throw");
        oos.writeObject(instance);
    }
}

Так что крайне маловероятно, что вам когда-либо понадобится заботиться о сериализуемости Void, не так ли?

0 голосов
/ 11 февраля 2011

Возможно сериализовать примитив 'void' по умолчанию, почему объект 'Void' не расширяет Serializable?

Void не несет значения, поэтому оннет смысла сериализовать его.

Разве это не значит, что void! = Void?

Верно, как int! = IntegerНо когда вы сериализуете и десериализуете два целых числа, newint == oldint (я имею в виду int, а не Integer !!!).Такая конструкция не была бы возможна с void.Просто не имеет смысла сериализовать ничего.

...