什么是对象序列化?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (10)
  • 关注 (0)
  • 查看 (184)

什么是“对象序列化”?你能用一些例子解释一下吗?

提问于
用户回答回答于

序列化是将对象转换成一系列字节,这样对象就可以很容易地保存到持久存储中,或者通过通信链路传输。然后可以将字节流反序列化——转换为原始对象的副本。

用户回答回答于

序列化是将Java对象转换为字节数组的过程,然后再以其保留的状态返回到对象。对于各种事情都很有用,比如通过网络发送对象或者将东西缓存到磁盘。

用户回答回答于

序列化是在存储介质(例如文件或内存缓冲区)中保存对象的过程,或者通过二进制形式将其传输到网络连接上。序列化的对象是JVM独立的,可以由任何JVM重新序列化。在这种情况下,“在内存中”的java对象状态被转换为一个字节流。这个类型的文件不能被用户理解。它是一种特殊类型的对象,即由JVM (Java虚拟机)重用。这个序列化对象的过程也称为压缩或编组对象。

要序列化的对象必须实现java.io.Serializable接口。对象的默认序列化机制写入对象的类、类签名以及所有非transient 和非静态字段的值。

class ObjectOutputStream extends java.io.OutputStream implements ObjectOutput,

ObjectOutput接口扩展了DataOutput接口,并向文件中添加用于序列化对象和写入字节的方法。大ObjectOutputStream扩展java.io.OutputStream和实施ObjectOutput接口。它将对象、数组和其他值序列化为流。的构造函数ObjectOutputStream写成:

ObjectOutput ObjOut = new ObjectOutputStream(new FileOutputStream(f));

上面的代码已用于创建ObjectOutput类的ObjectOutputStream( )构造函数,该构造函数接受FileOuputStream作为参数。

ObjectOutput接口通过实现ObjectOutputStream ObjectOutputStream构造为序列化对象。

在java中反序列化对象

序列化的相反操作称为反序列化,即从一系列字节中提取数据称为反序列化,也称为充气或解组。

ObjectInputStream扩展java.io.InputStream和实施ObjectInput接口。它从输入流反序列化对象、数组和其他值。的构造函数ObjectInputStream写成:

ObjectInputStream obj = new ObjectInputStream(new FileInputStream(f));

上面的程序代码创建ObjectInputStream类来反序列化已由ObjectInputStream实现。上面的代码使用FileInputStream class which holds the specified file object which has to be deserialized because the ObjectInputStream()构造函数需要输入流。

用户回答回答于

以下是对序列化的详细说明

序列化:

序列化是持久化对象状态的过程。它以字节序列的形式表示和存储。这可以存储在一个文件中。从文件中读取对象状态并恢复它的过程称为反序列化。

为什么需要序列化?

在现代体系结构中,总是需要存储对象状态并检索它。例如,在Hibernate中,为了存储对象,我们应该使类可序列化。它所做的就是,一旦以字节的形式保存对象状态,它就可以被传输到另一个系统,然后系统可以从状态读取并检索类。对象状态可以来自数据库或不同的JVM,也可以来自单独的组件。在序列化的帮助下,我们可以检索对象状态。

代码示例和说明:

首先,让我们看看项目类:

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;
        }
}

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

这是允许类可序列化的接口。

现在我们可以看到一个名为串行VersionUID初始化为长变量。编译器根据类和类属性的状态计算此数目。当JVM从文件中读取对象的状态时,这个数字将帮助JVM识别对象的状态。

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

如果字段不可序列化,则必须标记为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。我们使用了写对象对象的方法在文件中写入对象。

对于反序列化,我们使用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]

注意项目成本从反序列化对象是因为它不是写的。

我们已经在本文的第一部分中讨论了Java序列化的基础知识。

现在让我们深入讨论一下它是如何工作的。

首先,让我们从连续的。

串行VersionUID用作可序列化类中的版本控制。

如果您没有显式声明序列化VersionUID,JVM将根据可序列化类的各种属性为您自动声明。

计算串行符的Java算法

阶级的名字。

  1. 类修饰符作为32位整数写入。
  2. 按名称排序的每个接口的名称。
  3. 对于按字段名排序的每个字段(私有、静态和私有瞬态字段除外):字段名。字段的修饰符以32位整数形式写入。字段的描述符。
  4. 如果存在类初始化器,则写出以下内容:方法的名称。
  5. 该方法的修饰符java.lang.Reflt.Modifier.STATIC作为32位整数编写。
  6. 该方法的描述符,()V。
  7. 对于每个按方法名称和签名排序的非私有构造函数:方法的名称。方法的修饰符作为32位整数写入.。方法的描述符。
  8. 对于每个按方法名称和签名排序的非私有方法:方法的名称。方法的修饰符作为32位整数写入.。方法的描述符。
  9. SHA-1算法在DataOutputStream生成的字节流上执行,并生成5个32位值sha。0.4哈希值是从sha-1消息摘要的三32位值组装而来的.。如果消息摘要的结果,即五个32位字H0h1h2h3h4在一个名为sha的五个int值数组中,则将按以下方式计算散列值:

long hash = ((sha[0] >>> 24) & 0xFF) | > ((sha[0] >>> 16) & 0xFF) << 8 | > ((sha[0] >>> 8) & 0xFF) << 16 | > ((sha[0] >>> 0) & 0xFF) << 24 | > ((sha[1] >>> 24) & 0xFF) << 32 | > ((sha[1] >>> 16) & 0xFF) << 40 | > ((sha[1] >>> 8) & 0xFF) << 48 | > ((sha[1] >>> 0) & 0xFF) << 56;

Java序列化算法

序列化对象的算法描述如下: 1.它写出与实例关联的类的元数据。 2.它递归地写出超类的描述,直到它找到对象... 3.一旦完成元数据信息的编写,就会从与实例相关的实际数据开始。但这一次,它从最上层的超类开始。 4.它递归地写入与实例相关的数据,从最少的超类开始到派生最多的类。

要记住:

  1. 不能序列化类中的静态字段。 公共类A实现可序列化的{String;静态String StaticString=“I‘t Serialable”;}
  2. 如果读类中的序列化版本uid不同,它将抛出一个InvalidClassException例外。
  3. 如果一个类实现可序列化,那么它的所有子类也将是可序列化的。

公共类A实现可序列化{...};公共类B扩展A{...}/也可序列化

  1. 如果一个类具有另一个类的引用,则所有引用都必须是可序列化的,否则将不会执行序列化过程。在这种情况下,NotSerializableException在运行时抛出。

例:

public class B{
     String s,
     A a; // class A needs to be serializable i.e. it must implement Serializable
}
用户回答回答于

序列化是将对象的状态转换成比特的过程,这样它就可以存储在硬盘上。当您反序列化同一个对象时,它将保留它的状态。它让您无需手动保存对象的属性就可以重新创建对象。

用户回答回答于

序列化意味着在java中持久化对象。如果您希望保存对象的状态,并希望稍后重新构建状态(可能在另一个JVM中),可以使用序列化。

注意,对象的属性只会被保存。如果您想再次恢复对象,您应该拥有类文件,因为成员变量只会被存储,而不是成员函数。

例:

ObjectInputStream oos = new ObjectInputStream(                                 
                                 new FileInputStream(  new File("o.ser")) ) ;
SerializationSample SS = (SearializationSample) oos.readObject();

Searialable是一个标记接口,它标志着您的类是可序列化的。标记接口意味着它只是一个空接口,使用该接口将通知JVM这个类可以序列化。

用户回答回答于

尽管了解了机器人的类结构和具有序列化数据的地球科学家,却无法对能使机器人工作的数据进行反序列化。

Exception in thread "main" java.io.InvalidClassException:
SerializeMe; local class incompatible: stream classdesc
:
用户回答回答于

序列化在内存中取一个“live”对象,并将其转换为可以存储在某个地方的格式(如。在内存中,在磁盘上),然后将“反序列化”返回到活动对象中。

用户回答回答于

什么是序列化?

将对象转换为字节,将字节转换回对象(反序列化)。

什么时候使用序列化?

当我们想要持久化对象的时候。当我们希望对象存在于JVM的生存期之后。

例子:

ATM:当帐户持有人试图通过ATM从服务器取钱时,帐户持有人的信息(如取款详细信息)将被序列化并发送到服务器,在那里详细信息被反序列化并用于执行操作。

如何在java中执行序列化。

  1. 实施java.io.Serializable 接口(实现接口里面的方法).
  2. 持久化对象:使用java.io.ObjectOutputStream类,是一个过滤器流,它是围绕一个较低级别字节流的包装器(用于将对象写入文件系统或通过网络线路传输扁平对象并在另一侧重建)。
- `writeObject(<<instance>>)` - to write an object 
- `readObject()`  - to read an serialized Object

记住:

序列化对象时,只保存对象的状态,而不保存对象的类文件或方法。

当您序列化一个2字节的对象时,您会看到51个字节的序列化文件。

步骤如何序列化和反序列化对象。

答:它是如何转换成51字节文件的?

  • 首先写入序列化流(STREAM_MAGIC= "AC ED 和STREAM_VERSION=version 到JVM种。
  • 然后,它写出与实例关联的类的元数据(类的长度,类的名称,serialVersionUID)。
  • 然后递归地写出超类的元数据,直到找到java.lang.Object...
  • 然后从与实例关联的实际数据开始。
  • 最后,将与实例关联的对象的数据从元数据写入实际内容。

这将回答一些常见的问题:

  1. 如何不序列化类中的任何字段。 答:使用transient关键字
  2. 当子类被序列化时,父类是否被序列化?

答:不,如果父级没有扩展可序列化接口父字段,则不能序列化。

  1. 当父类被序列化时,子类是否被序列化? 答:是的,在默认情况下,子类也会被序列化。
  2. 如何避免子类被序列化?

答: .重写写对象和readObject方法并抛出NotSerializableException...

你也可以在子类中标记所有字段。

  1. 一些系统级别的类,如Thread、OutputStream及其子类和套接字是不可序列化的.
用户回答回答于

您可以将序列化看作是将对象实例转换为字节序列(可能是二进制的,也可能不取决于实现)的过程。

当您希望通过网络传输一个对象数据时,它非常有用,例如从一个JVM到另一个JVM。

在Java中,序列化机制是内置在平台中的,但是您需要实现系列化接口使对象可序列化。

还可以通过将属性标记为transient...

需要注意的是,序列化的是对象的“值”或内容,而不是类定义。因此,方法没有序列化。

下面是一个非常基本的示例,并附有注释以便于阅读:

import java.io.*;
import java.util.*;

// This class implements "Serializable" to let the system know
// it's ok to do it. You as programmer are aware of that.
public class SerializationSample implements Serializable {

    // These attributes conform the "value" of the object.

    // These two will be serialized;
    private String aString = "The value of that string";
    private int    someInteger = 0;

    // But this won't since it is marked as transient.
    private transient List<File> unInterestingLongLongList;

    // Main method to test.
    public static void main( String [] args ) throws IOException  { 

        // Create a sample object, that contains the default values.
        SerializationSample instance = new SerializationSample();

        // The "ObjectOutputStream" class has the default 
        // definition to serialize an object.
        ObjectOutputStream oos = new ObjectOutputStream( 
                               // By using "FileOutputStream" we will 
                               // Write it to a File in the file system
                               // It could have been a Socket to another 
                               // machine, a database, an in memory array, etc.
                               new FileOutputStream(new File("o.ser")));

        // do the magic  
        oos.writeObject( instance );
        // close the writing.
        oos.close();
    }
}

当我们运行这个程序时,文件“o.ser创建了

如果我们更改以下值:某些整数以,例如Integer.MAX_VALUE,我们可以比较输出,看看有什么不同。

这里有一个截图,正好显示了这个区别:

你能看出不同之处吗?;)

所属标签

可能回答问题的人

  • 西风

    renzha.net · 站长 (已认证)

    7 粉丝1 提问9 回答
  • 四无君

    0 粉丝0 提问3 回答
  • 拉布拉多拉不多

    1 粉丝0 提问2 回答
  • 小书虫

    0 粉丝1 提问2 回答

扫码关注云+社区

领取腾讯云代金券