0

编辑:使用此解决方案解决

我有一个非常奇怪的问题。我正在尝试反序列化具有两个已更改的类的 HashMap,尽管程度不大。无法发布代码,因为它受版权保护。

值得注意的是,类 2 的构造函数有一个附加字段(字符串名称),因为我试图反序列化的文件已被序列化。

似乎 Class 1 正试图转换为 String 作为 Class 2 的名称字段。

我一直在使用 ObjectInputStream 和 ObjectOutputStream。让我感到困惑的部分是 Class 1 从来没有 Class 2 类型的成员变量,而 HashMap 类型一直是有序的。我真的不知道发生了什么,所以我尝试了在这个问题中发布的解决方案,该解决方案与我得到的异常相同,但是尽管对 ClassLoaders 进行了大量研究,但我仍然不太了解,也没有真正了解知道使用什么 ClassLoader 作为“自由变量”。

这是我遇到的问题的堆栈跟踪(类名已更改):

java.lang.ClassCastException: cannot assign instance of [CLASS 1] to field [CLASS 2].name of type java.lang.String in instance of [CLASS 2]
at java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2034)
at java.io.ObjectStreamClass.setObjFieldValues(ObjectStreamClass.java:1207)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1975)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1893)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1775)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1327)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:349)
at java.util.HashMap.readObject(HashMap.java:1030)
at sun.reflect.GeneratedMethodAccessor27.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:969)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1775)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1327)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:349)

代码片段:

    final ClassLoader loader = this.getClass().getClassLoader();    //attempt to solve ClassCastException issue below.
            FileInputStream fin = new FileInputStream(targetFile);
            InputStream buffer = new BufferedInputStream(fin);
            ObjectInputStream ois = new ObjectInputStream(buffer)   {

                /*
                 * As seen here: https://stackoverflow.com/questions/2358886/how-can-i-deserialize-the-object-if-it-was-moved-to-another-package-or-renamed
                 */
                @Override
                protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException    {
                    ObjectStreamClass resultClassDescriptor = super.readClassDescriptor();

                    if (resultClassDescriptor.getName().equals("Class 1 [old path]"))
                        resultClassDescriptor = ObjectStreamClass.lookup(Class 1 [new path].class);                    
                    else if (resultClassDescriptor.getName().equals("Class 2 [old path]"))
                        resultClassDescriptor = ObjectStreamClass.lookup(Class 2 [new path].class);

                    return resultClassDescriptor;
                }

                /*
                 * As seen here : https://stackoverflow.com/questions/9110677/readresolve-not-working-an-instance-of-guavas-serializedform-appears
                 */
                @SuppressWarnings("rawtypes")
                @Override
                protected Class resolveClass(ObjectStreamClass objectStreamClass)
                        throws IOException, ClassNotFoundException {
                    return Class.forName(objectStreamClass.getName(), true, loader);
                }
            };

            Object ob = ois.readObject(); //exception happens here
            HashMap<Class 1, Class 2> loadedMap = (HashMap<Class 1, Class 2>)ob;

            ois.close();
            buffer.close();
            fin.close();
4

1 回答 1

0

看起来您正在分配两个不兼容的类。

class_1 = new class_2()

class_1 必须是 class_2 或 class_2 的超类。看起来

resultClassDescriptor = ObjectStreamClass.lookup(Class 2 [new path].class);

可能是罪魁祸首。//................... 编辑

class A{}
class B extends A{}
class C{}

A obj = new B();,不会给出错误,因为 A 是 B 的超类。如果你obj转换为 C 类,那么它会抛出 ClassCastException

C cobj = (C) obj;

于 2013-09-04T17:00:33.163 回答