在反序列化时,实现类的接口参考的序列化失败

时间:2010-07-19 15:43:14

标签: java serialization

我会尽可能简明扼要地解释我的问题。我觉得我正在尝试的东西可能本质上是错误的,但不知怎的,我相信它应该有效。所以请随意将这篇文章视为仅仅对序列化机制的澄清。

所以,我有一个由类实现的接口[暗示它们存在于不同的文件中]。

// ----- SomeInterface.java
public interface SomeInterface extends Serializable
{
    public void setMsg(String msg);
    public void printMsg();
}

// ----- SomeImpl.java
public class SomeImpl implements SomeInterface
{
    private String msg;
    public void setMsg(String msg)
    {
        this.msg = msg;
    }


    public void printMsg()
    {
        System.out.println("Msg is: " +msg);
    }

}

现在我序列化[tt] SomeImpl [/ tt]类的实例:

...
    public void SomeMethInSomeClass()
    { 
        FileOutputStream fos = new FileOutputStream(new File("c:/test.ser"));
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        SomeInterface si = new SomeImpl();

        si.setMsg("blah blah");
        oos.writeObject(test);

        oos.close();
        fos.close();
        System.out.println("------ done -------");
    }

现在在一个单独的项目中,我有一个上面的应用程序的JAR,其中包含接口SomeInterface,但不包含实现类SomeImpl。在此应用程序中,如果我尝试执行以下操作:

....
....
    public void deserialiserMethod() throws Exception
    {
        FileInputStream fis = new FileInputStream(new File("c:/test.ser"));
        ObjectInputStream ois = new ObjectInputStream(fis);
        SomeInterface si = null;

        System.out.println("------ reading ----------");
        si = (SomeInterface) ois.readObject();
        si.printMsg();
        System.out.println("------- done ----------");
        ois.close();
        fis.close();
    }
....

...我得到ClassNotFoundException [SomeImpl]。现在我知道我的其他项目在其类路径中没有SomeImpl类。但是不应该转换为父接口的引用来处理那个依赖关系?

感谢您的投入!

2 个答案:

答案 0 :(得分:1)

这不是强制转换的问题,这是序列化对象的类类型的问题。如果您的代码从不直接引用SomeImpl类并不重要,事实仍然是序列化对象仍然属于该类型。

考虑一下 - 如果不是SomeImpl,反序列化对象将成为哪个类的实例?必须在某处定义字段,如果不在SomeImpl中,那么在哪里?

即使您要反序列化对象并将其强制转换为java.lang.Object,您也必须遇到与对象的实际表示形式和运行时类型相同的问题。

答案 1 :(得分:0)

如果反序列化过程无法访问该类,则不能拥有该实例。

如果类未被默认ObjectInputStream实现使用的“最新”类加载器加载,则可以提供在其他位置加载的其他类。覆盖ObjectInputStream.resolveClass以提供课程。与RMI一样,您可以通过覆盖ObjectOutputStream.annotateClass来“注释”流,以指示应该在哪里找到类。