`
paddy.w
  • 浏览: 506135 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Understand the Serializable and serialVersionUID

    博客分类:
  • Java
阅读更多
        看了一篇简单介绍serialVersionUID的文章,在这里结合javaAPI文档和自己的理解说一下Serializable和serialVersionUID。

        一、Serializable

        在JavaAPI中已经将这个问题说的很明白了,下面只是简单的概括一下。

        1、Serializable是一个标志性接口,没有任何成员变量和方法。需要序列化一个类时只需要声明实现这个接口即可。
        2、如果类A中组合了类B的对象的化,序列化类A对象的同时会序列化类B对象,前提是类A和类B都实现了Serializable接口。
        3、如果类B继承类A,那么序列化类B分为下面两中情况:
          (1)类A没有实现Serializable接口,而类B实现了。那么根据JavaAPI中的说明,如果需要序列化类B,需要保证类A和类B都有无参的构造方法,如果无法默认构造,则必须显式声明。没有无参构造方法的话,在运行时会报异常。
           用这种方式试了一下,虽然可以序列化类A继承来的属性(public、protected、包访问),但是不能正确读取,读出来是null,类B自身特有的属性没问题。有待进一步验证。
          (2)类A实现了Serializable接口(类B实不实现无所谓,因为继承类A)。通过类B给继承于类A的变量和自身特有的变量赋值,并进行序列化。序列化成功,并可以正确读取。

        二、serialVersionUID

        serialVersionUID用于可序列化类的版本控制。如果不显式的声明一个serialVersionUID,JVM会基于这个序列化类的不同方面特征自动生成一个。
        具体的可以参见JavaAPI文档的Serializable接口说明。

        下面用一个例子来说明serialVersionUID的版本控制作用。

        下面的类实现了Serializable接口,并且自定义了serialVersionUID=1L
public class Address implements Serializable{
 
	   private static final long serialVersionUID = 1L;
 
	   String street;
	   String country;
 
	   public void setStreet(String street){
		   this.street = street;
	   }
 
	   public void setCountry(String country){
		   this.country = country;
	   }
 
	   public String getStreet(){
		   return this.street;
	   }
 
	   public String getCountry(){
		   return this.country;
	   }
 
	   @Override
	   public String toString() {
    	   return new StringBuffer(" Street : ")
    	   .append(this.street)
    	   .append(" Country : ")
    	   .append(this.country).toString();
	   }
}


        WriteObject类将Address类的对象写入磁盘文件address.ser。
public class WriteObject{
 
	public static void main (String args[]) {
 
	   Address address = new Address();
	   address.setStreet("wall street");
	   address.setCountry("united state");
 
	   try{
 
		FileOutputStream fout = new FileOutputStream("c:\\address.ser");
		ObjectOutputStream oos = new ObjectOutputStream(fout);   
		oos.writeObject(address);
		oos.close();
		System.out.println("Done");
 
	   }catch(Exception ex){
		   ex.printStackTrace();
	   } 
	}
}


        ReadObject类读取保存了Address对象的文件address.ser
public class ReadObject{
 
   public static void main (String args[]) {
 
	   Address address;
 
	   try{
 
		   FileInputStream fin = new FileInputStream("c:\\address.ser");
		   ObjectInputStream ois = new ObjectInputStream(fin);
		   address = (Address) ois.readObject();
		   ois.close();
 
		   System.out.println(address);
 
	   }catch(Exception ex){
		   ex.printStackTrace(); 
	   } 
   }
}


        测试类
public class SerialSample {

	public static void main(String[] args) {
		WriteObject wo=new WriteObject();
		ReadObject ro=new ReadObject();
		wo.write();
		ro.read();
	}
}


        运行测试类,控制台的显示可以知道对象被序列化存入磁盘文件并正确的读出。下面在Address类中修改serialVersionUID=2L。注释掉测试类中wo.write()这一句并再次执行。控制台出现下面的错误:
java.io.InvalidClassException: *.*.*.Address; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2


        这是因为序列化的时候serialVersionUID=1L,修改之后我们把一个serialVersionUID=2L的声明引用指向了反序列化后的serialVersionUID=1L的对象。JVM发现了不匹配,所以报错。
        这也说明了serialVersionUID在序列化和反序列化的过程中必须匹配。

        缺省serialVersionUID。
        如果不显式的指定一个serialVersionUID,JVM会根据自有的算法来生成一个缺省的serialVersionUID。
        这个缺省的serialVersionUID的计算对类的细节高度敏感,并且会因为不同的JVM而发生变化。在不同的JVM之间进行反序列化会导致InvalidClassExceptions异常。
分享到:
评论

相关推荐

    Java中serialVersionUID的解释

    Java 中的 serialVersionUID 是一个非常重要的概念,在实现 Serializable 接口的类中,它扮演着至关重要的角色。那么,serialVersionUID到底是什么?它又是如何生成的?在本篇文章中,我们将详细地解释 ...

    详述IntelliJ IDEA 中自动生成 serialVersionUID 的方法(图文)

    在安装 GenerateSerialVersionUID 插件后,可以在 Inspections 设置页面中勾选 Serializable class without 'serialVersionUID',并且还可以在 Severity 中设置提示级别,如 Warning、Error 等,默认为 Warning。...

    序列化 serializable demo

    例如,`MySerializable.java`和`Product.java`两个文件可能分别代表实现了`Serializable`接口的类。`MySerializable`可能是自定义的一个示例类,而`Product`可能是表示产品的类,它们都包含了可序列化的属性。 在`...

    java类中serialVersionUID详解.pdf

    当实现 `java.io.Serializable` 接口的类未明确声明 `serialVersionUID` 时,Java 序列化机制将根据编译后的 Class 文件自动生成一个 `serialVersionUID`。此规则下,即使多次重新编译,只要 Class 文件内容不变...

    Serializable java序列号

    // getters and setters... } ``` 序列化和反序列化的操作通常使用`ObjectOutputStream`和`ObjectInputStream`来完成: ```java // 序列化 try (FileOutputStream fos = new FileOutputStream("object.ser"); ...

    轉Serializable至Stream

    // getters and setters } ``` 现在,如果我们有一个`MySerializableClass`的实例`obj`,并希望将其转化为字节数组(即字节流),我们可以使用`ByteArrayOutputStream`和`ObjectOutputStream`。这是基本步骤: ``...

    可序列化接口Serializable

    在Java编程语言中,`Serializable`接口是一个非常重要的概念,它是实现对象持久化的关键。本文将深入探讨`Serializable`接口的细节,以及与其相关的高级知识。 `Serializable`接口是Java中的一个标记接口,没有包含...

    Intent传递对象Serializable

    本教程将详细讲解如何通过Serializable接口来实现Intent对象的传递。 首先,了解Serializable接口。在Java中,Serializable是用于序列化和反序列化的接口。当一个类实现了这个接口,它的实例就可以被转化为一串字节...

    coreJava: serialVersionUID

    在Java编程中,`serialVersionUID` 是一个非常重要的概念,特别是在序列化和反序列化过程中。这个特殊标识符主要用于版本控制,确保不同版本的类在序列化和反序列化时能够正确匹配。当我们讨论`serialVersionUID`时...

    Java对象Serializable接口实现详解

    在实现Serializable接口时,需要注意的是必须提供一个固定的serialVersionUID变量,这个变量用于标识该类的版本号,以便在反序列化时可以正确地还原对象。例如,在上面的例子中,我们定义了一个User类,并实现了...

    Serializable的增删改查

    Serializable的增删改查操作,已经经过验证,可以直接运行。

    java->serializable深入了解

    java->serializable深入了解 java->serializable深入了解 java->serializable深入了解

    Laravel开发-serializable-values

    在Laravel框架中,"serializable-values"是一个关键概念,它涉及到对象的序列化与反序列化,这对于数据存储和传输至关重要。在这个话题下,我们将深入探讨Laravel如何处理可序列化的值,以及如何利用Luminark提供的...

    Serializable在C#中的作用.NET 中的对象序列化

    ### C#中Serializable的作用与对象序列化详解 #### 一、引言 在现代软件开发中,特别是基于.NET框架的应用程序开发中,对象序列化是一项非常重要的技术。它允许将对象的状态转换为一种持久的形式(如文件或网络传输...

    Serializable-master.zip

    《深入理解Java序列化:serialVersionUID与序列化过程解析》 在Java编程中,序列化是一种将对象的状态转换为字节流的过程,以便可以存储在磁盘上或在网络上传输。这一过程对于实现持久化、跨网络通信以及分布式计算...

    Android序列化——Serializable与Parcelable

    本文将深入探讨两种主要的序列化方式:Serializable和Parcelable,并比较它们的优缺点以及适用场景。 首先,我们来了解什么是序列化。序列化是将对象的状态转换为可存储或可传输的形式的过程。在Android中,这个...

    bundle传递基本数据,Parcelable类型数据,Serializable类型数据

    本篇将详细介绍如何通过`Bundle` 传递基本数据类型、Parcelable类型数据以及Serializable类型数据。 ### 一、基本数据类型的传递 在Android中,基本数据类型包括int、boolean、float、double、char等。通过`put()`...

    java serializable 序列化与反序列化

    // getters and setters } ``` 4. **序列化过程**:使用`ObjectOutputStream`的`writeObject()`方法将对象写入流,如下所示: ```java MyObject obj = new MyObject(); try (ObjectOutputStream oos = new ...

    serialVersionUID作用全面解析

    在实现 Serializable 接口的类中,如果没有显示地定义 serialVersionUID,Java 序列化机制会根据编译的 Class 自动生成一个 serialVersionUID 作序列化版本比较用。 在实际应用中,serialVersionUID 的应用场景非常...

    析Android中的Serializable序列化.rar_Serializable _android

    3. 版本兼容性:当类结构发生变化时(如添加、删除或修改字段),需要考虑序列化版本号(serialVersionUID)以保持序列化数据的兼容性。如果没有显式声明,Java会自动生成一个版本号,但更改类结构可能导致反序列化...

Global site tag (gtag.js) - Google Analytics