简体   繁体   English

为什么 java.lang.Void 不可序列化?

[英]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?默认情况下可以序列化原始“void”,为什么对象“Void”不扩展 Serializable?

Added example:添加示例:

The RootImplementation will have a compilation error saying "Void is not within its bound" since it does not extend Serializable. RootImplementation 将有一个编译错误,指出“Void 不在其范围内”,因为它没有扩展 Serializable。 Though would 'someMethod' be declared with 'void' it would be no problem.尽管将“someMethod”声明为“void”,但它不会有问题。

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).好的,为了响应您的示例,如果您将方法更改为void它将不起作用,因为该方法必须具有返回类型(即使 Java 现在允许在重写方法中使用协变返回类型)。 The discussion of void confuses the issue.void的讨论混淆了这个问题。

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 通常是一个不错的选择,但要使 Void 起作用,返回类型必须是 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. Void 无法实现 API 中的每个接口,因为有人可能想使用它来指示类型参数的 null 返回。

There are three ways to look at your problem:可以通过三种方式来查看您的问题:

  1. Serializable is an overly restrictive type declaration. Serializable 是一个过于严格的类型声明。 You should really be using Object.你真的应该使用 Object. Do you really need it to be Serializable?你真的需要它是可序列化的吗?
  2. You can just declare the type parameter as Serializable, and in practice return null.您可以将类型参数声明为 Serializable,实际上返回 null。 This dosn't fully indicate that you are returning null every time, but it may be enough.这并不完全表明您每次都返回 null,但这可能就足够了。
  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.您可以声明自己的名为 Null 的类,它实现了 Serializable,可能作为 Root 接口的静态嵌套类,并在这种情况下将其用作类型参数。 You will find making your own Null object is not that uncommon, even in the standard JDK there is (a private) one.您会发现创建自己的 Null 对象并不少见,即使在标准 JDK 中也有(私有)对象。

The javadoc is clear: javadoc 很清楚:

The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword Void 类是一个不可实例化的占位符类,用于保存对代表 Java 关键字的 Class 对象的引用

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)对于第二个问题: void != Void (如果您考虑 != 在非 Java 表达式中)

Yes void is a keyword and Void a class.是的void是一个关键字,而Void是一个类。

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.lang.Void b/c 你只能用 null 初始化它。 Java doesn't care if a class implements java.io.Serializable if it's null . Java 不在乎一个类是否实现java.io.Serializable如果它是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:引用 Javadocs:

The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword void. Void 类是一个不可实例化的占位符类,用于保存对表示 Java 关键字 void 的 Class 对象的引用。

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”,为什么对象“Void”不扩展 Serializable?

Void doesn't carry a value, hence it makes no sense to serialize it. Void 不携带值,因此序列化它是没有意义的。

Doesn't this mean that void != Void ?这不是说 void != Void 吗?

True, just as int != Integer.没错,就像 int != Integer 一样。 But when you serialize and deserialize two ints, newint==oldint (I mean int , not Integer !!!).但是当你序列化和反序列化两个整数时, newint==oldint (我的意思是int ,而不是Integer !!!)。 No such construct would be possible with void . 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.只有当你有一个 Void 类型的字段时它才有用,这真的没有意义。 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.只要不做,就可以序列化包含Void字段的类的实例。 In order to create an instance of Void, you need to use reflection in order to use the private constructor.为了创建 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);
    }
}

So it's extremely improbably you ever need to care about the serializability of Void, isn't it?因此,您几乎不可能需要关心 Void 的可序列化性,不是吗?

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.其他人已经解释了为什么对于永远无法实例化以实现Serializable的类型没有意义,以及为什么void不是原始类型或可序列化的。

To address the code in your edit, I think you should just change the R extends Serializable bound to just R .为了解决您编辑中的代码,我认为您应该将R extends Serializable绑定更改为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.大多数可Serializable泛型类型不要求它们的类型参数是可Serializable ……它们只是声明如果您在其中放入不可序列化的内容,它们也将不可序列化。 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. Void只是为了表明一个方法只能返回null ,遗憾的是没有办法直接声明 null 类型。 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.因为 jvm Void 只是一个扩展 Object 的普通类,因此不能用于其他类或接口,这使得您的示例中的 Void 无用。

Since your method wont return anything but null you could replace Void with something like the following:由于您的方法不会返回除 null 之外的任何内容,因此您可以将 Void 替换为以下内容:

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.至于调用 void 原语,void 表示没有值,返回 void 的方法不返回 void 类型的值,而是从字面上不返回任何内容。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法将void转换为java.lang.Void - Cannot convert void to java.lang.Void java.lang.Void vs void vs Null - java.lang.Void vs void vs Null java.lang.Void 和 void 有什么区别? - What is the difference between java.lang.Void and void? Mockito问题 - 当Stubber中的(java.lang.Void)无法应用于void时 - Mockito issue - when(java.lang.Void) in Stubber cannot be applied to void AsyncTask引发错误“由java.lang.ClassCastException引起:java.lang.Object []无法转换为doinbackground()上的java.lang.Void []” - AsyncTask throwing Error “Caused by java.lang.ClassCastException: java.lang.Object[] cannot be cast to java.lang.Void[]” on doinbackground() Reactive Mongo - DeleteAllBy... 查询 - 找不到类型 class java.lang.Void 的 PersistentEntity - Reactive Mongo - DeleteAllBy… query - Couldn't find PersistentEntity for type class java.lang.Void 不兼容的类型。 找到:'javax.mail.PasswordAuthentication',需要:'java.lang.Void' - Incompatible types. Found: 'javax.mail.PasswordAuthentication', required: 'java.lang.Void' 为什么Java Swing可序列化? - Why is Java Swing serializable? java:为什么ResultSet不是Serializable? - java: Why ResultSet is not Serializable? 为什么Java Bean必须可序列化? - Why Java Beans have to be serializable?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM