[英]Why is java.lang.Void not Serializable?
默认情况下可以序列化原始“void”,为什么对象“Void”不扩展 Serializable?
添加示例:
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;
}
}
好的,为了响应您的示例,如果您将方法更改为void
它将不起作用,因为该方法必须具有返回类型(即使 Java 现在允许在重写方法中使用协变返回类型)。 对void
的讨论混淆了这个问题。
您想要做的是将类型参数声明为“将只返回空值”。 Void 通常是一个不错的选择,但要使 Void 起作用,返回类型必须是 Object。 Void 无法实现 API 中的每个接口,因为有人可能想使用它来指示类型参数的 null 返回。
可以通过三种方式来查看您的问题:
javadoc 很清楚:
Void 类是一个不可实例化的占位符类,用于保存对代表 Java 关键字的 Class 对象的引用
因为你不能使用它,所以它不需要是可序列化的(反射的东西除外)。
对于第二个问题: void != Void (如果您考虑 != 在非 Java 表达式中)
是的void
是一个关键字,而Void
是一个类。
我会把它作为社区维基放在这里
你可以(反)序列化java.lang.Void
b/c 你只能用 null 初始化它。 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());
}
}
引用 Javadocs:
Void 类是一个不可实例化的占位符类,用于保存对表示 Java 关键字 void 的 Class 对象的引用。
由于该类是不可实例化的,因此不能反序列化。 因此不需要序列化支持。
默认情况下可以序列化原始“void”,为什么对象“Void”不扩展 Serializable?
Void 不携带值,因此序列化它是没有意义的。
这不是说 void != Void 吗?
没错,就像 int != Integer 一样。 但是当你序列化和反序列化两个整数时, newint==oldint (我的意思是int
,而不是Integer
!!!)。 void
不可能有这样的构造。 什么都不序列化是没有任何意义的。
只有当你有一个 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 的可序列化性,不是吗?
其他人已经解释了为什么对于永远无法实例化以实现Serializable
的类型没有意义,以及为什么void
不是原始类型或可序列化的。
为了解决您编辑中的代码,我认为您应该将R extends Serializable
绑定更改为R
。 大多数可Serializable
泛型类型不要求它们的类型参数是可Serializable
……它们只是声明如果您在其中放入不可序列化的内容,它们也将不可序列化。 这通常是一个很好的做法,因为在编译器级别过于努力地强制执行可序列化可能会咬你(如你所见)。
Void
只是为了表明一个方法只能返回null
,遗憾的是没有办法直接声明 null 类型。 因为 jvm Void 只是一个扩展 Object 的普通类,因此不能用于其他类或接口,这使得您的示例中的 Void 无用。
由于您的方法不会返回除 null 之外的任何内容,因此您可以将 Void 替换为以下内容:
public final SerializebaleVoid extends Object implements Serializeable{
private SerializeableVoid(){}
}
至于调用 void 原语,void 表示没有值,返回 void 的方法不返回 void 类型的值,而是从字面上不返回任何内容。
如果您使用的是 apache 公共库,则有一个 org.apache.commons.lang3.ObjectUtils.Null 可以扩展 Serializable。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.