代码之家  ›  专栏  ›  技术社区  ›  Ritwik Bose

序列化是什么意思?

  •  117
  • Ritwik Bose  · 技术社区  · 14 年前

    Serializable 在爪哇?或者一般来说,就这点而言。。。

    10 回复  |  直到 14 年前
        1
  •  139
  •   Daniël Camps    8 年前

    Serialization 将一个对象从内存持久化为一个位序列,例如保存到磁盘上。反序列化是相反的—从磁盘读取数据以创建对象。

    在您的问题的上下文中,它是一个接口,如果在类中实现,则该类可以由不同的序列化程序自动序列化和反序列化。

        2
  •  46
  •   William Kinaan    9 年前

    虽然大多数用户已经给出了答案,但我想为那些需要它的人添加一个例子来解释这个想法:

    public class Person implements java.io.Serializable {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        public String firstName;
        public String lastName;
        public int age;
        public String address;
    
        public void play() {
            System.out.println(String.format(
                    "If I win, send me the trophy to this address: %s", address));
        }
        @Override
        public String toString() {
            return String.format(".....Person......\nFirst Name = %s\nLast Name = %s", firstName, lastName);
        }
    }
    

    Person william = new Person();
            william.firstName = "William";
            william.lastName = "Kinaan";
            william.age = 26;
            william.address = "Lisbon, Portugal";
    

    可以将该对象序列化为多个流。我将对两条溪流这样做:

    序列化到标准输出:

    public static void serializeToStandardOutput(Person person)
                throws IOException {
            OutputStream outStream = System.out;
            ObjectOutputStream stdObjectOut = new ObjectOutputStream(outStream);
            stdObjectOut.writeObject(person);
            stdObjectOut.close();
            outStream.close();
        }
    

    序列化到文件:

    public static void serializeToFile(Person person) throws IOException {
            OutputStream outStream = new FileOutputStream("person.ser");
            ObjectOutputStream fileObjectOut = new ObjectOutputStream(outStream);
            fileObjectOut.writeObject(person);
            fileObjectOut.close();
            outStream.close();
        }
    

    然后:

    public static void deserializeFromFile() throws IOException,
                ClassNotFoundException {
            InputStream inStream = new FileInputStream("person.ser");
            ObjectInputStream fileObjectIn = new ObjectInputStream(inStream);
            Person person = (Person) fileObjectIn.readObject();
            System.out.println(person);
            fileObjectIn.close();
            inStream.close();
        }
    
        3
  •  42
  •   David    14 年前

    这意味着类的实例可以转换成字节流(例如,保存到文件中),然后再转换回类。这种重新加载可能发生在程序的不同实例中,甚至可能发生在不同的机器上。序列化(在任何语言中)涉及各种各样的问题,尤其是当您在可序列化对象中有对其他对象的引用时。

        4
  •  16
  •   Pritam Banerjee Ashish Karnavat    8 年前

    Here is a detailed explanation of the Serialization :(我自己的博客)

    序列化:

    序列化需要什么?

    代码示例和说明:

    首先让我们看看Item类:

    public class Item implements Serializable{
    
        /**
        *  This is the Serializable class
        */
        private static final long serialVersionUID = 475918891428093041L;
        private Long itemId;
        private String itemName;
        private transient Double itemCostPrice;
        public Item(Long itemId, String itemName, Double itemCostPrice) {
            super();
            this.itemId = itemId;
            this.itemName = itemName;
            this.itemCostPrice = itemCostPrice;
          }
    
          public Long getItemId() {
              return itemId;
          }
    
         @Override
          public String toString() {
              return "Item [itemId=" + itemId + ", itemName=" + itemName + ", itemCostPrice=" + itemCostPrice + "]";
           }
    
    
           public void setItemId(Long itemId) {
               this.itemId = itemId;
           }
    
           public String getItemName() {
               return itemName;
           }
           public void setItemName(String itemName) {
                this.itemName = itemName;
            }
    
           public Double getItemCostPrice() {
                return itemCostPrice;
            }
    
            public void setItemCostPrice(Double itemCostPrice) {
                 this.itemCostPrice = itemCostPrice;
            }
    }
    

    在上面的代码中可以看到 项目 类实现 可序列化

    这是使类可以序列化的接口。

    现在我们可以看到一个变量 序列版本ID 初始化为长变量。编译器根据类的状态和类属性来计算这个数字。这个数字将帮助jvm在从文件中读取对象的状态时识别对象的状态。

    序列化运行时与每个可序列化类a相关联 反序列化以验证序列化的发送方和接收方 关于序列化。如果接收器已为 对象的SerialVersionId与 对应发送方的类,则反序列化将导致 InvalidClassException无效。可序列化类可以声明自己的 通过声明一个名为 “serialVersionUID”必须是静态的、最终的且类型为long: serializable类没有显式声明serialVersionUID, 然后序列化运行时将计算默认值 规范。但是,强烈建议 可序列化类显式声明serialVersionUID值,因为 默认的serialVersionUID计算对类非常敏感 因此在执行过程中会导致意外的InvalidClassExceptions 反序列化。因此,要保证serialVersionUID的一致性 跨不同java编译器实现的值,可序列化 强烈建议显式serialVersionUID声明使用 立即声明的类--serialVersionUID字段不可用 用作继承成员。

    如果您注意到我们使用的另一个关键字 瞬变 .

    如果字段不可序列化,则必须将其标记为transient。在这里我们标记了 项目成本价 是暂时的,不想写在文件里

    public class SerializationExample {
    
        public static void main(String[] args){
            serialize();
           deserialize();
        } 
    
        public static void serialize(){
    
             Item item = new Item(1L,"Pen", 12.55);
             System.out.println("Before Serialization" + item);
    
             FileOutputStream fileOut;
             try {
                 fileOut = new FileOutputStream("/tmp/item.ser");
                 ObjectOutputStream out = new ObjectOutputStream(fileOut);
                 out.writeObject(item);
                 out.close();
                 fileOut.close();
                 System.out.println("Serialized data is saved in /tmp/item.ser");
               } catch (FileNotFoundException e) {
    
                      e.printStackTrace();
               } catch (IOException e) {
    
                      e.printStackTrace();
               }
          }
    
        public static void deserialize(){
            Item item;
    
            try {
                    FileInputStream fileIn = new FileInputStream("/tmp/item.ser");
                    ObjectInputStream in = new ObjectInputStream(fileIn);
                    item = (Item) in.readObject();
                    System.out.println("Serialized data is read from /tmp/item.ser");
                    System.out.println("After Deserialization" + item);
            } catch (FileNotFoundException e) {
                    e.printStackTrace();
            } catch (IOException e) {
                   e.printStackTrace();
            } catch (ClassNotFoundException e) {
                   e.printStackTrace();
            }
         }
    }
    

    在上面我们可以看到一个序列化和反序列化对象的例子。

    为此我们用了两个班。对于序列化对象,我们使用了ObjectOutputStream。我们使用writeObject方法将对象写入文件。

    对于反序列化,我们使用了ObjectInputStream,它从文件中读取对象。它使用readObject从文件中读取对象数据。

    上述代码的输出如下:

    Before SerializationItem [itemId=1, itemName=Pen, itemCostPrice=12.55]
    Serialized data is saved in /tmp/item.ser
    After DeserializationItem [itemId=1, itemName=Pen, itemCostPrice=null]
    

    注意 项目成本价 因为它不是书面的。

        5
  •  11
  •   Jigar Joshi    14 年前

    序列化包括将对象的当前状态保存到流中,并从该流中恢复等效对象。流充当对象的容器

        6
  •  6
  •   Waldmann AphexMunky    4 年前

    Serializable类似于接口调用,但更像是在运行时调用序列化子系统的标志。上面说这个物体可以保存。将保存所有对象实例变量,但无可序列化对象和标记为volatile的对象除外。

    想象一下,你的应用程序可以改变颜色作为一个选项,而不保持外部设置,你将需要改变颜色,每次你运行它。

        7
  •  4
  •   Mdhar9e    13 年前

    序列化是一种将对象和数据存储或写入文件的技术。通过使用 ObjectOutputStream FileOutputStream 班级。这些类有其特定的方法来持久化对象。喜欢 writeObject();

    用数字清楚地解释。 See Here for more info

        8
  •  2
  •   nanospeck    11 年前

    从另一个角度呈现。序列化是一种称为“标记接口”的接口。标记接口是不包含方法声明的接口,但是 仅将实现接口的类指定(或标记)为具有 一些财产。如果你理解多态性,这将非常有意义。在可序列化标记接口的情况下ObjectOutputStream.write如果(Object)方法的参数未实现接口,则该方法将失败。这是java中的一个潜在错误,可能是ObjectOutputStream.write(可序列化)

    强烈推荐:阅读 约书亚·布洛赫的《有效Java》

        9
  •  2
  •   Asif Mushtaq    9 年前

    正在将对象的状态写入文件/网络或任何位置。(表示Java对象支持的窗体到文件支持的窗体或网络支持的窗体)

    反序列化:

        10
  •  1
  •   Greg Sexton    14 年前

        11
  •  0
  •   Nomade    4 年前

    序列化对象意味着将其状态转换为字节流,以便字节流可以还原回对象的副本。如果Java对象的类或任何超类实现java.io.Serializable 接口或其子接口,java.io.Externalizable. 反序列化是将对象的序列化形式转换回对象副本的过程

    点击 here