2011-02-11 3 views
5

Можно выполнить сериализацию примитива «void» по умолчанию, почему объект «Пустота» не расширяет Serializable?Почему java.lang.Void не Serializable?

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

RootImplementation будет иметь ошибку компиляции, говоря «Пустота не в его границы», так как оно не распространяется Serializable. Хотя будет объявлен «someMethod» с «void», это не проблема.

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

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

+1

Там нет такого понятия, как примитивную пустоту. И у Void никогда нет экземпляра, и я не могу придумать пример использования, где это будет поле в классе. Но если это так, вы всегда можете сделать это преходящим, так как оно всегда будет нулевым. – Yishai

+4

Что вы подразумеваете под «возможно сериализовать примитив« void »по умолчанию? Нет данных для сериализации ... можете ли вы привести пример того, что вы имеете в виду? –

+0

Я добавлю пример, 2 сек. –

ответ

5

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

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

Есть три способа смотреть на вашей проблеме:

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

Спасибо за ответ. 1. Как упоминает ColinD; большинство просто разделит Serialziable общего типа, поскольку само объявление класса подразумевает не сохранение несериализуемых объектов в реализации. Хотя, поскольку довольно много людей собираются использовать интерфейс и выполнять реализации, я хочу, чтобы он был настолько полезен, насколько это возможно, чтобы не сделать ошибку. 2. Я не хочу, чтобы возможное расширение могло возвращать что-либо еще, кроме void (или null в этом случае, поскольку Void должен использоваться). 3. Вот как я это сделал в данный момент, хотя я хотел задать вопрос и посмотреть, есть ли у кого-то лучшее решение. –

+0

@ Томас Форсман, класс, реализующий сериализуемый, не означает, что он может быть сериализован. Рассмотрим это: 'private void writeObject (ObjectOutputSteam out) {throw new NotSerializableException (getClass(). GetName());}' Я использую это, чтобы некоторые расширенные классы никогда не достигали формы сериализации. – bestsss

4

Javadoc ясно:

Класс Пустоты является uninstantiable класса заполнителя для хранения ссылки на объект класса, представляющий ключевое слово Java

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


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

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

1

Процитируем Javadocs:

Пустота класс является uninstantiable класса заполнителя содержать ссылку на объект класса, представляющего пустоту ключевого слова Java.

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

0

можно сериализовать примитивную «пустоту» по-умолчанию, почему не объект «Пустота» продлить Serializable?

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

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

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

+0

Почему downvote? Что не так? –

0

Это было бы полезно, если бы у вас было поле типа 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); 
    } 
} 

Так что это очень неправдоподобно вам всегда нужно заботиться о сериализуемости Пустоты, не так ли?

0

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

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

0

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

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

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

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

2

я положу его здесь, как comminity-вика

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

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

 
[email protected] 
[email protected] 

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());   
    } 
} 
Смежные вопросы