简体   繁体   中英

Why is java.lang.Void not Serializable?

It is possible to serialize the primitive 'void' per default, why does not the object 'Void' extend Serializable?

Added example:

The RootImplementation will have a compilation error saying "Void is not within its bound" since it does not extend Serializable. Though would 'someMethod' be declared with 'void' it would be no problem.

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

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

OK, in response to your example, no if you changed the method to void it would not work, as the method has to have a return type (even if Java now allows covariant return types in overridden methods). The discussion of void confuses the issue.

What you want to do is declare a type parameter as a "will just return null." Void is generally a good choice for that, but for Void to work, the return type has to be Object. Void can't implement every interface in the API just because someone might want to use it to indicate a null return on a type parameter.

There are three ways to look at your problem:

  1. Serializable is an overly restrictive type declaration. You should really be using Object. Do you really need it to be Serializable?
  2. You can just declare the type parameter as Serializable, and in practice return null. This dosn't fully indicate that you are returning null every time, but it may be enough.
  3. You can declare your own class called Null which implements Serializable, perhaps as a static nested class of the Root interface, and use that as the type parameter in this case. You will find making your own Null object is not that uncommon, even in the standard JDK there is (a private) one.

The javadoc is clear:

The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword

Because you can not use it, it does not need to be Serializable (except reflection stuff).


And for the second question: void != Void (if you are think about != in a not java expression)

Yes void is a keyword and Void a class.

I will put it here as comminity-wiki

Thou can (de)serialize java.lang.Void b/c you can initialize it with null only. Java doesn't care if a class implements java.io.Serializable if it's null .

Result of the code

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());        
    }
}

To quote the Javadocs:

The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword void.

Since the class is uninstantiable, it cannot be deserialized. Ergo no need for serialization support.

It is possible to serialize the primitive 'void' per default, why does not the object 'Void' extend Serializable?

Void doesn't carry a value, hence it makes no sense to serialize it.

Doesn't this mean that void != Void ?

True, just as int != Integer. But when you serialize and deserialize two ints, newint==oldint (I mean int , not Integer !!!). No such construct would be possible with void . It just doesn't make any sense to serialize nothing.

It'd be only useful if you had a field of type Void, which really makes no sense. You'd also need to actually assign it an instance, which again makes no sense. As long as you don't do it, you can serialize the instance of class containing the Void field. In order to create an instance of Void, you need to use reflection in order to use the private constructor.

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);
    }
}

So it's extremely improbably you ever need to care about the serializability of Void, isn't it?

Others have explained why it doesn't make sense for a type that can never be instantiated to implement Serializable and why void isn't a primitive or serializable.

To address the code in your edit, I think you should just change the R extends Serializable bound to just R . Most generic types that are Serializable do not require that their type parameters be Serializable ... they simply state that if you put something in them that isn't serializable, they won't be serializable either. This is generally a good practice, as trying too hard to enforce serializability at the compiler level can bite you (as you see here).

Void is only intended to show that a method can only return null , sadly there is no way to declare the null-type directly. For the jvm Void is only a normal class extending Object and as such cannot be used in place for other classes or interfaces, this makes Void for your example useless.

Since your method wont return anything but null you could replace Void with something like the following:

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

As to calling void a primitive, void shows the absence of a value, a method returning void does not return a value of type void instead it literally does not return anything.

如果您使用的是 apache 公共库,则有一个 org.apache.commons.lang3.ObjectUtils.Null 可以扩展 Serializable。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM