[英]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.