Java向后兼容性:readObject()如何读取具有不同serialVersionUID的相同类名对象?

Java向后兼容性:readObject()如何读取具有不同serialVersionUID的相同类名对象?,java,backwards-compatibility,serialversionuid,Java,Backwards Compatibility,Serialversionuid,此套接字将继续接收一些旧对象和新对象 同名。但是,如果我直接使用readObject,它将抛出 致命的例外。我们中的一些人会建议忽略旧对象或 更改旧的目标代码。这对我来说是不可能改变的 客户代码。我需要处理这个问题 向后兼容性 //旧类已发布(我无法更改) 公共类Apple扩展HashMap{ 私有静态最终长serialVersionUID=1L; } //旧类已发布(我无法更改) 公共类Apple扩展HashMap{ 私有静态最终长serialVersionUID=2L; } //我本

此套接字将继续接收一些旧对象和新对象 同名。但是,如果我直接使用readObject,它将抛出 致命的例外。我们中的一些人会建议忽略旧对象或 更改旧的目标代码。这对我来说是不可能改变的 客户代码。我需要处理这个问题 向后兼容性



//旧类已发布(我无法更改)
公共类Apple扩展HashMap{
私有静态最终长serialVersionUID=1L;
}
//旧类已发布(我无法更改)
公共类Apple扩展HashMap{
私有静态最终长serialVersionUID=2L;
}

//我本地的新类(1L或2L仍然无法轻松解决问题)
公共类Apple扩展HashMap{
私有静态最终长serialVersionUID=2L;
}
在readObject()的行中, 我得到了一个致命的例外:

java.io.InvalidClassException本地类不兼容:stream classdesc SerialVersionId=1,本地类SerialVersionId=2

我如何读取这两种Apple对象数据(Hashmap)?

多谢各位

Java:
readObject()
如何读取具有不同
serialVersionUID
的两个类

很容易。他们是不同的班级。为什么不应该呢

serialVersionUID中有两个名称相同但不同的类

所以他们是不同的阶级。你的问题

我得到了一个致命的例外:

这与不同包中具有相同名称的两个类没有任何关系。这意味着您在发送方部署了一个版本为
serialVersionUID=2
的类,在接收方部署了另一个版本为
serialVersionUID=1
。苏蒂安:不要那样做。部署相同的版本:在本例中,使用
2
的版本,因为这是流中的版本。通常,在不确切知道自己在做什么的情况下,不应更改
serialVersionUID

在我的情况下,有两个版本的类发送到我身边。1L和2L


不,没有。有一个版本发送(2L)和另一个版本接收(1L)。不要这样做。

只要我们扩展ObjectInputStream,

我们将访问stream SerialVersionUID以与本地SerialVersionUID进行比较。



import java.io.IOException;
导入java.io.InputStream;
导入java.io.InvalidClassException;
导入java.io.ObjectInputStream;
导入java.io.ObjectStreamClass;
公共类DecompressableInputStream扩展了ObjectInputStream{
公共解压缩InputStream(InputStream in)引发IOException{
超级(in),;
}
受保护的ObjectStreamClass readClassDescriptor()引发IOException,ClassNotFoundException{
ObjectStreamClass resultClassDescriptor=super.readClassDescriptor();
类localClass;
试一试{
localClass=Class.forName(resultClassDescriptor.getName());
}catch(classnotfounde异常){
System.err.println(“没有“+resultClassDescriptor.getName()的本地类”);
返回resultClassDescriptor;
}
ObjectStreamClass localClassDescriptor=ObjectStreamClass.lookup(localClass);
if(localClassDescriptor!=null){
最终长localSUID=localClassDescriptor.getSerialVersionUID();
final long streamSUID=resultClassDescriptor.getSerialVersionId();
if(streamSUID!=localSUID){
System.err.println(“潜在致命的反序列化操作”);
resultClassDescriptor=localClassDescriptor;
}
}
返回resultClassDescriptor;
}
}
希望能有帮助


(归功于此)

“它们完全相同”-不,根据您的评论,它们在不同的包中。完全限定类名在序列化(以及一般情况下)中很重要。您是否询问如何将一个类的序列化对象作为另一个类的实例来读取?它们是两种不同的类型。串行版本UID与此无关。强制转换到
HashMap
并读取其条目。@qxz是。我只想读取该数据。您确定自序列化对象以来类的
serialVersionUID
没有更改吗?这就是你的例外情况。
Socket s = ss.accept();
ObjectInputStream lvStream = new ObjectInputStream(s.getInputStream());
Object lvObject = lvStream.readObject();
// The old class but released ( I cannot change it )
public class Apple extends HashMap<String, String> {
    private static final long serialVersionUID = 1L;
}
// The old class but released ( I cannot change it )
public class Apple extends HashMap<String, String> {
    private static final long serialVersionUID = 2L;
}
// The new class in my local ( 1L or 2L still would not solve the issue easily )
public class Apple extends HashMap<String, String> {
    private static final long serialVersionUID = 2L;
}
java.io.InvalidClassException local class incompatible : stream classdesc serialVersionUID = 2, local class serialVersionUID = 1
Socket s = ss.accept();
// use the extended ObjectInputStream ( DecompressibleInputStream )
DecompressibleInputStreamlvStream = new DecompressibleInputStream(s.getInputStream());
Object lvObject = lvStream.readObject();
import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;

public class DecompressibleInputStream extends ObjectInputStream {

    public DecompressibleInputStream(InputStream in) throws IOException {
        super(in);
    }

    protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
        ObjectStreamClass resultClassDescriptor = super.readClassDescriptor();
        Class<?> localClass;
        try {
            localClass = Class.forName(resultClassDescriptor.getName()); 
        } catch (ClassNotFoundException e) {
            System.err.println("No local class for " + resultClassDescriptor.getName());
            return resultClassDescriptor;
        }
        ObjectStreamClass localClassDescriptor = ObjectStreamClass.lookup(localClass);
        if (localClassDescriptor != null) {
            final long localSUID = localClassDescriptor.getSerialVersionUID();
            final long streamSUID = resultClassDescriptor.getSerialVersionUID();
            if (streamSUID != localSUID) {
                System.err.println("Potentially Fatal Deserialization Operation.");
                resultClassDescriptor = localClassDescriptor;
            }
        }
        return resultClassDescriptor;
    }
}