将具有相同serialVersionUID,字段,方法的类型A的类反序列化为类型B

时间:2019-06-06 08:30:05

标签: java serialization

给我java.lang.ClassCastException:slz.A无法转换为slz.B为什么?这两个类具有相同的字段和方法。为什么我在反序列化时无法将类型A的序列化对象转换为类型B?

public class A implements Serializable {

  private  String var1;
  private String var2;
  private static final long serialVersionUID = 4L;

  public String getVar1() {
    return var1;
  }

  public void setVar1(String var1) {
    this.var1 = var1;
  }

  public String getVar2() {
    return var2;
  }

  public void setVar2(String var2) {
    this.var2 = var2;
  }
}


public class B implements Serializable {

  private  String var1;
  private String var2;
  private static final long serialVersionUID = 4L;

  public String getVar1() {
    return var1;
  }

  public void setVar1(String var1) {
    this.var1 = var1;
  }

  public String getVar2() {
    return var2;
  }

  public void setVar2(String var2) {
    this.var2 = var2;
  }

  @Override
  public String toString() {
    return var1 + " " + var2;
  }
}

public class Test {

  public static void main(String[] args)  {
    A a = new A();
    a.setVar1("d");
    a.setVar2("e");

    B b = null;

    try(FileOutputStream fileOut = new FileOutputStream("Test.ser");
        ObjectOutputStream outputStream = new ObjectOutputStream(fileOut);
        FileInputStream inputStream = new FileInputStream("Test.ser");
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);){
      outputStream.writeObject(a);
      b = (B) objectInputStream.readObject();

    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
  }
}

两个类A和B实现可序列化,它们具有相同的字段和方法以及相同的序列号ID

3 个答案:

答案 0 :(得分:3)

毕竟它们是不同的类。在序列化期间,该过程将需要跟踪其类型,因为在反序列化期间,运行时需要知道要实例化哪种类型。当类型不匹配时,您将获得类强制转换异常。

但是,您应该研究readResolve()方法,该方法将在反序列化期间调用,并且可用于创建与流不同的类型。如果您将以下方法添加到类A中,则反序列化将起作用:

public Object readResolve() throws ObjectStreamException{
  return new B();
}

从Javadocs的Serializable接口中:

 * <p>Serializable classes that need to designate an alternative object to be
 * used when writing an object to the stream should implement this
 * special method with the exact signature:
 *
 * <PRE>
 * ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
 * </PRE><p>
 *
 * This writeReplace method is invoked by serialization if the method
 * exists and it would be accessible from a method defined within the
 * class of the object being serialized. Thus, the method can have private,
 * protected and package-private access. Subclass access to this method
 * follows java accessibility rules. <p>
 *
 * Classes that need to designate a replacement when an instance of it
 * is read from the stream should implement this special method with the
 * exact signature.
 *
 * <PRE>
 * ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
 * </PRE><p>
 *
 * This readResolve method follows the same invocation rules and
 * accessibility rules as writeReplace.<p>

答案 1 :(得分:2)

您不能反序列化A到B,因为它们是不同的类。它们实际上是相同的没关系,但它们仍然是不同的类。就像试图将狗反序列化为猫一样,它们的腿数相同,但是它们是不同的动物。

答案 2 :(得分:-1)

public class A extends B {}

将您的A类更改为上面的代码,这应该可以工作。发生类强制转换异常是因为您的类A和B都不属于同一类型。反序列化过程返回,对象类型为A,而您试图将其强制转换为B,这就是失败的原因。