当前位置: 首页 > 知识库问答 >
问题:

扩展类的Java序列化

谭学名
2023-03-14

在java序列化类Mp3player扩展电子设备实现序列化在这个代码中超级类电子设备是不实现序列化的。

 import java.io.*;
 class ElectronicDevice { 
      ElectronicDevice() 
      {
           System.out.print("ed "); 
      }
  }
 class Mp3player extends ElectronicDevice implements Serializable {
       Mp3player() 
       { 
          System.out.print("mp "); 
       }
 }
class MiniPlayer extends Mp3player {
     MiniPlayer()
     { 
         System.out.print("mini "); 
     }
     public static void main(String[] args) {
          MiniPlayer m = new MiniPlayer();
          try {
                 FileOutputStream fos = new FileOutputStream("dev.txt");
             ObjectOutputStream os = new ObjectOutputStream(fos);
                 os.writeObject(m); os.close();

                 FileInputStream fis = new FileInputStream("dev.txt");
                 ObjectInputStream is = new ObjectInputStream(fis);
                 MiniPlayer m2 = (MiniPlayer) is.readObject(); 
                 is.close();
                 System.out.println();
          } catch (Exception x) {
                System.out.print("x "); 
          }
     }
  }

共有3个答案

范侯林
2023-03-14

这是超类序列化的规则:

如果你是一个可序列化的类,但是你的超类是不可序列化的,那么你从该超类中继承的任何实例变量都将被重置为它们在对象的原始构造过程中给出的值。这是因为非序列化的类构造函数将运行。

因此,如果向ElectronicDevice添加一些实例变量,请注意超类的状态将不会序列化。(除非超类实现可序列化)

印瑾瑜
2023-03-14

因为超类没有实现可序列化的内容,所以超类不会序列化。只有子类的内容会序列化。当您反序列化时,超类的默认构造函数将被执行,超类的字段将被初始化,就像您调用默认构造函数一样。

下面的例子说明了这一点。

public class SerializationTest {

    public static class Base {
        private String name;

        public Base() {
            this.name = "johnDow";
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public static class Sub extends Base implements Serializable {
        private static final long serialVersionUID = 1L;
        private String age;

        public String getAge() {
            return age;
        }

        public void setAge(String age) {
            this.age = age;
        }
    }

    public static void main(String[] args) throws Exception {
        ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteArrayOS);
        Sub s = new Sub();
        s.setName("name");
        s.setAge("10");
        out.writeObject(s);
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(byteArrayOS.toByteArray()));
        Sub d = (Sub) ois.readObject();
        System.out.println(d.getName() + "-" + d.getAge());
    }
}

打印出来的是

johnDow-10
秋光熙
2023-03-14

否。在序列化过程中,只会写出和恢复可序列化对象的字段。

根据javadocs

在反序列化过程中,非序列化类的字段将使用类的公共或受保护的no-arg构造函数初始化。

其中,可序列化子类的字段将从流中恢复。

请查看此示例
此处电子设备不可序列化,其中asMp3player序列化。观察序列化过程中受尊重类的字段行为。

import java.io.*;
class ElectronicDevice  { 
  public int i = 0;
  protected ElectronicDevice() 
  {
       System.out.println("ed "); 
  }
}
class Mp3player extends ElectronicDevice implements Serializable {
   int j =0;
   Mp3player() 
   { 
       System.out.println("mp "); 
   }
}
class MiniPlayer extends Mp3player {
  MiniPlayer()
  { 
      System.out.println("mini "); 
  }
 public static void main(String[] args) {
      MiniPlayer m = new MiniPlayer();
      m.i = 30;
      m.j = 40;
      try {
             System.out.println("i value before serialization: "+m.i);//prints 30
             System.out.println("i value before serialization: "+m.j);//prints 40
             FileOutputStream fos = new FileOutputStream("dev.txt");
             ObjectOutputStream os = new ObjectOutputStream(fos);
             os.writeObject(m); os.close();

             FileInputStream fis = new FileInputStream("dev.txt");
             ObjectInputStream is = new ObjectInputStream(fis);
             MiniPlayer m2 = (MiniPlayer) is.readObject(); 
             is.close();
             System.out.println("i value after serialization: "+m2.i);//prints o
             System.out.println("j value after serialization: "+m2.j);//prints 40
             System.out.println();
        } catch (Exception x) {
            x.printStackTrace();
            System.out.print("x "); 
       }
   }
 }
 类似资料:
  • 扩展说明 将对象转成字节流,用于网络传输,以及将字节流转为对象,用于在收到字节流数据后还原成对象。 扩展接口 org.apache.dubbo.common.serialize.Serialization org.apache.dubbo.common.serialize.ObjectInput org.apache.dubbo.common.serialize.ObjectOutput 扩展配置

  • 问题内容: 在Java中,我可以以某种方式强制某个扩展了抽象类的类以将Object作为参数实现其构造函数吗? 就像是 问题答案: 您可以在抽象类中使用带有参数的构造函数(如果要禁止匿名子类,请将其保护)。 这样做会强制实现类具有显式构造函数,因为它必须使用一个参数来调用超级构造函数。 但是,您不能强制覆盖的类具有带有参数的构造函数。它总是可以伪造这样的参数:

  • 我想获得扩展特定父类的子类列表。例如:考虑下面的情况,其中B类扩展类A,C类扩展类B。 我想从java代码中获取子类名列表。i、 我需要编写一个java类,当我输入父类的名称时,它可以给我子类的列表。 提前感谢。

  • 用于SQLAlchemy查询结构的序列化程序/反序列化程序对象,允许“上下文”反序列化。 任何基于sqlAlchemy.sql的sqlAlchemy查询结构。 或sqlacalchemy.orm。 可以使用。结构引用的映射器、表、列、会话等不以序列化形式持久化,而是在反序列化时与查询结构重新关联。 用法与标准python pickle模块的用法几乎相同: from sqlalchemy.ext.s

  • 问题内容: 我知道一个类可以实现多个接口,但是可以扩展多个类吗?例如,我希望我的班级同时扩展我创建的类。这在Java中可行吗?这两个语句并收到一个错误。如果不可能,为什么呢?扩展,但我猜它也扩展了,因为它继承了字段,并且可以在需要对象的地方传递。同样,像Java中的所有类一样,它们扩展了类。那么为什么不能扩展一个以上的类呢? TransformGroup继承 那么,如果可能的话,正确的方法是什么?

  • 问题内容: 我怎样才能做到这一点: 另外,我想知道这种方法是否可行,因为我已经在类中创建了菜单,即ControlMenu,并且在其他活动中继续进行扩展。 问题答案: 你只能扩展一个类。并从许多来源实现接口。 扩展多个类不可用。我能想到的唯一解决方案不是继承任何一个类,而是每个类都有一个内部变量,并通过将对你对象的请求重定向到你希望它们去的对象来做更多的代理。 这是我想出的最好的解决方案。你可以从这