为什么java.lang.Void不可序列化?
可以按照默认值序列化基元“void”,为什么对象“void”不扩展Serializable 添加示例: RootImplementation将有一个编译错误,说明“Void不在其范围内”,因为它不扩展Serializable。 虽然“someMethod”会用“void”声明,但这不会有问题为什么java.lang.Void不可序列化?,java,void,Java,Void,可以按照默认值序列化基元“void”,为什么对象“void”不扩展Serializable 添加示例: RootImplementation将有一个编译错误,说明“Void不在其范围内”,因为它不扩展Serializable。 虽然“someMethod”会用“void”声明,但这不会有问题 public interface Root<R extends Serializable> extends Serializable { R someMethod(); } public
public interface Root<R extends Serializable> extends Serializable {
R someMethod();
}
public class RootImplementation implements Root<Void> {
public Void someMethod() {
return null;
}
}
公共接口根扩展可序列化{
R-somethod();
}
公共类Root实现实现了Root{
公共方法(){
返回null;
}
}
javadoc很清楚:
Void类是一个不可证明的类
用于保存引用的占位符类
到表示
Java关键字
因为您不能使用它,所以它不需要序列化(反射内容除外)
关于第二个问题:无效!=Void(如果您正在考虑!=在非java表达式中) 是
void
是一个关键字,void
是一个类 引用Javadocs:
Void类是一个不可实例化的占位符类,用于保存对表示Java关键字Void的类对象的引用
由于该类不可实例化,因此无法对其进行反序列化。因此,不需要序列化支持
可以序列化
每个默认值的基元“void”,为什么
不是对象“Void”扩展
可序列化
Void不携带值,因此序列化它是没有意义的
这不是意味着空虚吗!=空虚
正确,与int一样!=整数。但是当您序列化和反序列化两个int时,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);
}
}
公共类VoidSerializerDemo实现可序列化{
私人无效v;
公共静态void main(字符串[]args)引发异常{
最终VoidSerializerDemo实例=新的VoidSerializerDemo();
最终ByteArrayOutputStream bas=新ByteArrayOutputStream();
最终ObjectOutputStream oos=新ObjectOutputStream(BAS);
oos.writeObject(实例);
System.out.println(“确定:空工作”);
最终构造函数=Void.class.getDeclaredConstructor();
constructor.setAccessible(true);
instance.v=constructor.newInstance();
oos.reset();
System.out.println(“即将抛出”);
oos.writeObject(实例);
}
}
因此,您极不可能需要关心Void的可序列化性,不是吗?其他人已经解释了为什么不能实例化一个类型来实现
Serializable
是没有意义的,为什么Void
不是一个原语或可序列化的
要解决编辑中的代码问题,我认为您应该将
R extends Serializable
绑定更改为justR
。大多数可序列化的泛型类型不要求其类型参数为可序列化的。。。它们只是简单地声明,如果您在其中放入不可序列化的内容,它们也将不可序列化。这通常是一个很好的实践,因为在编译器级别过于努力地强制可序列化性可能会对您造成伤害(如您在这里看到的)。好的,作为对您的示例的响应,如果您将方法更改为void
,它将不起作用,因为该方法必须具有返回类型(即使Java现在允许在重写的方法中使用协变返回类型)
您要做的是将类型参数声明为“will just return null”。对于这一点,Void通常是一个不错的选择,但要使Void工作,返回类型必须是Object。Void不能实现API中的每个接口,因为可能有人想用它来指示类型参数的null返回
有三种方法可以解决您的问题:
Void
仅用于表明方法只能返回null
,遗憾的是,无法直接声明null类型。因为jvm Void只是一个普通的类扩展对象,因此不能用于其他类或接口,这使得Void对于您的示例来说毫无用处
由于您的方法只返回null,因此可以使用以下内容替换Void:
public final SerializebaleVoid extends Object implements Serializeable{
private SerializeableVoid(){}
}
至于调用void原语,void表示没有值,返回void的方法不会返回void类型的值,相反,它实际上不会返回任何内容。我将把它作为community wiki放在这里 您可以(反)序列化
java.lang.Void
b/c您可以仅使用null对其进行初始化。java不关心类是否实现了java.io.Serializable
,如果它是null
守则的结果
t1.VoidOut@19821f
t1.VoidOut@c17164
如果您使用的是apache commons库,则有一个org.apache.commons.lang3.Objec
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());
}
}