默认情况下可以序列化原语'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;
}
}
答案 0 :(得分:5)
好的,作为对你的例子的回应,如果你把方法改为void
它就行不通,因为该方法必须有一个返回类型(即使Java现在允许在重写方法中使用协变返回类型) 。对void
的讨论混淆了这个问题。
您要做的是将类型参数声明为“将只返回null”。 Void通常是一个很好的选择,但是要使Void工作,返回类型必须是Object。 Void无法实现API中的每个接口只是因为有人可能希望使用它来指示类型参数的null返回。
有三种方法可以查看您的问题:
答案 1 :(得分:4)
javadoc很清楚:
Void类是不可实现的 占位符类来保存引用 到表示对象的Class对象 Java关键字
因为你不能使用它,所以它不需要是Serializable(反射东西除外)。
对于第二个问题:void!= Void(如果你想到的话!=在非java表达式中)
是void
是一个关键字,Void
是一个类。
答案 2 :(得分:2)
我会把它作为comminity-wiki
放在这里你可以(de)序列化java.lang.Void
b / c你只能用null初始化它。如果一个类实现java.io.Serializable
null
,那么Java并不关心。
代码结果
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());
}
}
答案 3 :(得分:1)
引用Javadocs:
Void类是一个不可实例化的占位符类,用于保存对表示Java关键字void的Class对象的引用。
由于该类是不可实例化的,因此无法反序列化。 Ergo不需要序列化支持。
答案 4 :(得分:0)
可以序列化 默认为原始'void',为什么呢 不是'Void'对象延伸 序列化?
Void没有值,因此序列化它是没有意义的。
这是不是意味着虚空!=无效?
是的,就像int!=整数。但是当你序列化和反序列化两个整数时,newint == oldint(我的意思是int
,而不是Integer
!!!)。 void
不可能有这样的结构。将序列化没有任何意义。
答案 5 :(得分: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);
}
}
因此,你很需要关注Void的可串行性,不是吗?
答案 6 :(得分:0)
其他人已经解释了为什么对于一个永远无法实例化以实现Serializable
的类型以及为什么void
不是原始的或可序列化的类型没有意义。
要解决编辑中的代码,我认为您应该只将R extends Serializable
更改为R
。大多数Serializable
的通用类型不要求它们的类型参数为Serializable
......它们只是声明如果你在其中放入一些不可序列化的东西,它们也不会是可序列化的。这通常是一种很好的做法,因为在编译器级别上努力强制执行可序列化可能会让你感到困惑(如你所见)。
答案 7 :(得分:0)
Void
仅用于表明方法只能返回null
,遗憾的是没有办法直接声明null类型。对于jvm,Void只是一个扩展Object的普通类,因此不能用于其他类或接口,这使得Void对你的例子毫无用处。
由于你的方法不会返回null,你可以用以下内容替换Void:
public final SerializebaleVoid extends Object implements Serializeable{
private SerializeableVoid(){}
}
对于调用void一个原语,void表示没有值,返回void的方法不返回void类型的值,而是字面上不返回任何内容。
答案 8 :(得分:0)
如果您使用的是apache commons库,则有一个org.apache.commons.lang3.ObjectUtils.Null可以扩展Serializable。