[英]How do I peek in a java serialized object?
我有一個來自舊Java代碼的對象,我現在更改了序列化對象代碼。 我希望能夠讀取舊文件和新文件。 我需要在readObject中使用分支語句來執行以下操作:
if (next object is int -- just poking, it might be an Object)
{
// we know we are in version 1
} else {
// read new version of object
}
那可能嗎?
if (object instanceof Integer) {
... Do stuff
} else {
... Do other stuff
}
編輯:我想我應該擴展這一點。 您可以使用instanceof
檢查對象類型,但我不確定是否能夠使用像int
或char
這樣的原型。
最簡單的方法是使用舊類型保留舊成員變量,並為新類型添加新成員變量。 此外,您必須保持類的serialVersionUID相同。 然后,您的readObject()實現可以執行任何必要的操作,以將舊數據轉換為新數據。
原始對象:
public class MyObject {
private static final long serialVersionUID = 1234L;
private int _someVal;
}
新版本:
public class MyObject {
private static final long serialVersionUID = 1234L;
private int _someVal; //obsolete
private String _newSomeVal;
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException
{
in.defaultReadObject();
if(_someVal != 0) {
// translate _someVal to _newSomeVal
}
}
}
我相信使用自定義ObjectStreamField[] serialPersistentFields
, ObjectInputStream.GetField
和ObjectOutputStream.PutField
可以使用更復雜的選項。
好吧基本上問題是“我們如何檢查ObjectInputStream
下一個字段是基元還是對象?” 而我所能看到的答案是:你做不到。
這意味着我可以看到保持向后兼容性的最佳解決方案是永遠不會從原始版本中刪除原語 - 保持無用的信息會使規模大大增加,但這樣做很容易。
要添加新字段,我可以看到兩種方式:
保持較早的消息格式相同,只在末尾添加新對象 - 然后您可以通過消息大小輕松區分不同版本(或者更准確地說,當您獲取v1對象時,在讀取v2的數據時會獲得IOException)。 這更簡單,通常更受歡迎。
您可以將對象從v1更改為v2,然后執行簡單的instanceof
檢查。 如果你想添加原語是存儲他們的包裝器版本(即Integer
等)。 可以節省一些字節,但Java的序列化協議從一開始就沒有效率,所以真的不必要復雜。
ObjectInputStream
將加載並創建正確類的實例。
object = ois.readObject();
if (object instanceof YourNewShiny ){
// new style object
} else if (object instanceof YourOldBusted ){
// convert YourOldBusted to YourNewShiny
} else {
throw new ToyOutOfPram();
}
如果您有一個新類,這一切都很棒,但如果您以不兼容的方式更改了類,則ObjectInputStream
無法將類的舊版本反序列化為新表單。 如果是這種情況你幾乎被塞滿了。
選項:
ObjectInputStream
以檢測您的類類型(您可以使用serialVersionId來強化該類型) 只有第一個對我來說似乎是一個好主意。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.