Java基础入门总结之序列化和反序列化

目录
  • 基本概念
  • 序列化
  • 反序列化
  • 序列化和反序列化总结
    • 自定义序列化策略
      • Externalizable
      • transient
    • 静态变量
    • 序列化ID
    • 破坏单例
  • 总结

基本概念

  • Java中创建对象时,一旦程序终止,创建的对象可能就不存在.要想使得对象能够在程序不运行的状态下依然能够保存对象的信息,这时就需要用到序列化机制
  • 序列化机制:
    • 一个对象可以被表示为一个字节序列,包括:

      • 对象的数据
      • 对象的类型信息
      • 存储在对象中的数据类型
    • 将可序列化对象写入文件后,可以从文件中读取出来,根据对象的各种信息在内存中创建该对象. 这里的读取并创建对象的过程就是反序列化
    • 序列化和反序列化的整个过程都是JVM独立的.也就是说,在一个JVM中的序列化对象可以在另一个完全不同的JVM中反序列化对象
    • 一般情况下,序列化需要实现java.io.Serializable接口,使用ObjectInputStreamObjectOutputStream进行对象的读写操作
    • 还可以实现java.io.Externalizable接口,进行标准的序列化或者自定义的二进制格式.用来满足不同场景下的需求
  • Java序列化场景:
    • Java对象的字节序列持久化到硬盘中
    • 在网络上传输对象的字节序列
    • 进行远程方法调用RMI(Remote Method Invocation)
    • JVM运行结束时,还需要使用创建的对象
    • 需要将创建的对象保存下来以便后续的传输
    • 使得旧JVM创建的对象能够在一个新的JVM中运行
  • Java序列化注意点:
    • 对象的序列化保存的是对象成员变量对象,对象的序列化不会关注类中的静态变量
    • 类的序列化要保证类的所有属性都是可以序列化的,如果想要某个属性不被序列化.可以声明为瞬时态transient

序列化

  • Java对象序列化:

    • 使得可序列化的对象实现Serializable接口
    • 创建一个ObjectOutputStream输出流
    • 调用ObjectOutputStream对象的writeObject() 方法进行输出可序列化对象即可
  • 序列化示例:
public class Person implements Serializable {
	private String name;
	private int age;

	public Person() {
		System.out.println("无参构造...");
	}

	public Person(String name, int age) {
		this.name = name;
		this.age = age;
		System.out.println("有参构造...");
	}

	@Override
	public String toString() {
		return "Person{" +
				"name='" + name + "\'" +
				", age='" + age + "\'"
				"}";
	}
}
public class SerializableTest {
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		Person person = new Person("Lily", 20);

		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Person.txt"));
		oos.writeObject(person);
		oos.close();
	}
}

反序列化

  • Java对象反序列化:

    • 创建一个ObjectInputStream输入流
    • 调用ObjectInputStream对象的readObject() 方法得到序列化对象
public class  DeserializableTest {
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Person.txt"));
		Pesron person = (Person)ois.readObject(ois);
		System.out.println(person);
	}
}
  • 反序列化的对象是由JVM生成的对象,而不是通过类的构造函数生成的:

    • 反序列化对象时 ,JVM中要存在对象对应的类,否则会抛出ClassNotFoundException异常
    • 如果一个可序列化的类的成员不是基本类型,而是一个引用类型时,那么这个引用类型必须实现Serializable接口,否则会抛出NotSerializableException异常

序列化和反序列化总结

  • 实现Serializable接口就可以进行序列化的原因:

    • writeObject():

      • 首先会处理之前被编写的以及不可替换的对象
      • 如果有的对象被替换了,则检查被替换的对象
      • 最后如果对象都被替换了,则进行原始的检查
      • 原始的检查即检查被替换的对象类型是否为String类型,数组类型 ,Enum类型或者实现了Serializable接口,符合条件就可以对检查的对象执行相应的序列化操作,否则将会抛出NotSerializableException异常
    • 对于序列化的机制来说,如果对同一个对象执行多次序列化操作时,不会得到多个对象
      • 保存到磁盘的对象都有一个序列化编号,当程序试图进行序列化时,会检查该对象是否已经序列化
      • 只有对象从未被序列化过时,才会将此对象序列化为字节序列,如果对象已经序列化过,那么直接输出序列化编号
      • Java序列化机制不会重复序列化同一个对象,会记录已经序列化对象的编号,此时如果序列化了一个可变对象后,如果更改了对象的内容会再次进行序列化.如果没有更改内容,则不会将此对象转换为字节序列,只会保存序列化编号
  • 实现Serializable接口时可以重写writeObject() 方法和readObject() 方法:
    • 重写writeObject() 方法和readObject() 方法后,对象进行序列化和反序列化时,就会自动调用重写的writeObject() 方法和readObject() 方法
  • 实现Externalizable接口时可以重写writeExternal() 方法和readExternal() 方法:
    • 重写writeExternal() 方法和readExternal() 方法后,对象进行序列化和反序列化时,就会自动调用重写的writeExternal() 方法和readExternal() 方法

自定义序列化策略

Externalizable

  • 如果需要使得对象的一部分可以被序列化,另一部分数据不被序列化,此时可以自定义实现Externalizable接口,并且实现writeExternal()readExternal() 方法,可以在序列化和反序列化过程中自动调用来执行一些特殊的操作
  • 注意点:
    • Serializable接口实现的对象是与二进制的构建有关的,不会调用构造器
    • Externalizable接口实现的对象的所有构造函数都会被调用,所以要编写出类的无参和有参构造函数
  • 使用Externalizable自定义序列化示例:
public class CustomExternal implements Externalizable {

	private String name;

	private int code;

	public CustomExternal() {
		System.out.println("无参构造...");
	}

	public CustomExternal(String name, int code) {
		this.name = name;
		this.code = code;
		System.out.println("有参构造...");
	}

	@Override
	public void writeExternal(ObjectOutput out) throws IOException {
		System.out.println("执行writeExternal()方法...");
		out.writeObject(name);
		out.writeInt(code);
	} 

	@Override
	public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException {
		System.out.println("执行readExternal()方法...");
		name = (String) in.readObject();
		code = in.readInt();
	}

	@Override
	public String toString() {
		return "类:" + name + code;
	}

	public static void main(String[] args) throws IOException, ClassNotFoundException {
		CustomExternal custom = new CustomeExternal("oxford", 666);
		System.out.println(custom);

		// 序列化
		ObjectOutputStream out = new ObjectOutputStream(new FileInputStream("oxford.txt"));
		System.out.println("序列化对象...");
		out.writeObject(custom);
		out.close();

		// 反序列化
		ObjectInputStream in = new ObjectInputStream(new FileInputStream("oxford.txt"));
		System.out.println("反序列化对象...");
		custom = (CustomExternal) in.readObject();
		System.out.println(custom);
		in.close();
	}
}

有参构造...
类:oxford666
序列化对象...
执行writeExternal()方法...
反序列化对象...
无参构造...
执行readExternal()方法...
类:oxford666

  • 使用Externalizable自定义序列化时,为了保证序列化和反序列化的正确性,需要在writeExternal() 方法中将信息写入,并且在readExternal() 方法中恢复数据

transient

  • 可以使用transient关键字配置一些重要的信息比如密码等不进行序列化

    • transient关键字修饰的属性不会参与到序列化过程中
    • transient关键字修饰的属性在反序列化过程中,如果是引用数据类型,则返回null. 如果是基本数据类型,则返回默认值.不一定是基本数据类型序列化之前的值
  • 因为实现Externalizable接口的对象默认情况下不会保存任何字段,所以transient关键字只能和Serializable对象一起使用
  • transient关键字的使用场景:
    • 服务器端给客户端发送序列化对象数据时,对象中存在敏感数据
    • 比如密码字符串,在序列化时进行加密,客户端拥有解密的密钥,只有在客户端进行反序列化时,才会对密码进行读取
    • 这时就可以对密码字符串对象使用transient修饰,这样可以一定程度上保证序列化对象的数据安全

静态变量

  • 序列化时不会序列化静态变量

    • 静态变量属于类的状态,序列化中保存的是对象,也就是类的实例的状态
    • 序列化操作的是序列化中对象,也就是类的实例的状态,静态变量属于类的状态.所以序列化时不会对静态变量进行序列化

序列化ID

  • Java虚拟机进行反序列化:

    • 两个类的类路径和功能代码一致
    • 两个类的序列化ID,也就是serialVersionUID一致
  • 功能代码一致:
    • 序列化的类和反序列化的类所实现的功能和功能相关的代码是一样的
    • 示例:
      • 客户端A将类对象序列化客户端B, 客户端B进行反序列化
      • 这时要求AB都有这样的一个类文件,功能代码一致,并且都实现了Serializable接口
  • serialVersionUID的两种生成方式:
    • 默认值 1L
    • 通过类名,接口名和方法名以及属性随机生成的一个不重复的long类型的值
  • 在序列化ID,serialVersionUID相同的情况下,即使序列化对象的序列化属性修改,序列化对象也可以进行反序列化.因此如果只是修改了方法或者修改了静态变量或transient变量,只要不修改序列化ID, 那么反序列化就不会受到影响
  • 显式声明序列化ID,serialVersionUID的场景:
    • 如果需要类的不同版本对序列化兼容,要确保类的不同版本具有相同的serialVersionUID
    • 如果不需要类的不同版本对序列化兼容,要确保类的不同版本具有不同的serialVersionUID
    • 序列化一个类的实例后,如果修改一个字段或者增加一个字段,如果没有设置类的serialVersionUID, 就会导致无法反序列化旧的实例,会在反序列化时抛出异常
    • 序列化类添加SerialVersionUID后,如果修改一个字段或者增加一个字段,反序列化旧的实例时,修改的或者增加的字段的值会设置为初始化的值

破坏单例

  • 除了反射可以破坏单例模式外,序列化和反序列化后会得到一个新的对象,也可以破坏单例模式
  • 序列化和反序列化破坏单例模式:
    • 反序列化时,使用ObjectInputStream对象中的readObject() 方法
    • readObject() 的方法中调用readObject0() 方法
        public final Object readObject()
          throws IOException, ClassNotFoundException
      {
          if (enableOverride) {
              return readObjectOverride();
          }
    
          int outerHandle = passHandle;
          try {
              Object obj = readObject0(false);
              handles.markDependency(outerHandle, passHandle);
              ClassNotFoundException ex = handles.lookupException(passHandle);
              if (ex != null) {
                  throw ex;
              }
              if (depth == 0) {
                  vlist.doCallbacks();
              }
              return obj;
          } finally {
              passHandle = outerHandle;
              if (closed && depth == 0) {
                  clear();
              }
          }
      }
    • readObject0() 方法中会返回一个checkResolve(readOrdinaryObject(unshared))
        private Object readObject0(boolean unshared) throws IOException {
          boolean oldMode = bin.getBlockDataMode();
          if (oldMode) {
              int remain = bin.currentBlockRemaining();
              if (remain > 0) {
                  throw new OptionalDataException(remain);
              } else if (defaultDataEnd) {
                  throw new OptionalDataException(true);
              }
              bin.setBlockDataMode(false);
          }
    
          byte tc;
          while ((tc = bin.peekByte()) == TC_RESET) {
              bin.readByte();
              handleReset();
          }
    
          depth++;
          totalObjectRefs++;
          try {
              switch (tc) {
                  case TC_NULL:
                      return readNull();
    
                  case TC_REFERENCE:
                      return readHandle(unshared);
    
                  case TC_CLASS:
                      return readClass(unshared);
    
                  case TC_CLASSDESC:
                  case TC_PROXYCLASSDESC:
                      return readClassDesc(unshared);
    
                  case TC_STRING:
                  case TC_LONGSTRING:
                      return checkResolve(readString(unshared));
    
                  case TC_ARRAY:
                      return checkResolve(readArray(unshared));
    
                  case TC_ENUM:
                      return checkResolve(readEnum(unshared));
    
                  case TC_OBJECT:
                      return checkResolve(readOrdinaryObject(unshared));
    
                  case TC_EXCEPTION:
                      IOException ex = readFatalException();
                      throw new WriteAbortedException("writing aborted", ex);
    
                  case TC_BLOCKDATA:
                  case TC_BLOCKDATALONG:
                      if (oldMode) {
                          bin.setBlockDataMode(true);
                          bin.peek();
                          throw new OptionalDataException(
                              bin.currentBlockRemaining());
                      } else {
                          throw new StreamCorruptedException(
                              "unexpected block data");
                      }
    
                  case TC_ENDBLOCKDATA:
                      if (oldMode) {
                          throw new OptionalDataException(true);
                      } else {
                          throw new StreamCorruptedException(
                              "unexpected end of block data");
                      }
    
                  default:
                      throw new StreamCorruptedException(
                          String.format("invalid type code: %02X", tc));
              }
          } finally {
              depth--;
              bin.setBlockDataMode(oldMode);
          }
      }
    • readOrdinaryObject() 方法用于读取并返回普通对象. 这里的普通对象不包括String, Class, ObjectStreamClass, 数组或者枚举常量这些对象
    private Object readOrdinaryObject(boolean unshared)
          throws IOException
      {
          if (bin.readByte() != TC_OBJECT) {
              throw new InternalError();
          }
    
          ObjectStreamClass desc = readClassDesc(false);
          desc.checkDeserialize();
    
          Class<?> cl = desc.forClass();
          if (cl == String.class || cl == Class.class
                  || cl == ObjectStreamClass.class) {
              throw new InvalidClassException("invalid class descriptor");
          }
    
          Object obj;
          try {
              obj = desc.isInstantiable() ? desc.newInstance() : null;
          } catch (Exception ex) {
              throw (IOException) new InvalidClassException(
                  desc.forClass().getName(),
                  "unable to create instance").initCause(ex);
          }
    
          passHandle = handles.assign(unshared ? unsharedMarker : obj);
          ClassNotFoundException resolveEx = desc.getResolveException();
          if (resolveEx != null) {
              handles.markException(passHandle, resolveEx);
          }
    
          if (desc.isExternalizable()) {
              readExternalData((Externalizable) obj, desc);
          } else {
              readSerialData(obj, desc);
          }
    
          handles.finish(passHandle);
    
          if (obj != null &&
              handles.lookupException(passHandle) == null &&
              desc.hasReadResolveMethod())
          {
              Object rep = desc.invokeReadResolve(obj);
              if (unshared && rep.getClass().isArray()) {
                  rep = cloneArray(rep);
              }
              if (rep != obj) {
                  // Filter the replacement object
                  if (rep != null) {
                      if (rep.getClass().isArray()) {
                          filterCheck(rep.getClass(), Array.getLength(rep));
                      } else {
                          filterCheck(rep.getClass(), -1);
                      }
                  }
                  handles.setObject(passHandle, obj = rep);
              }
          }
    
          return obj;
      }
    • isInstantiable() 方法表示如果一个实现了Serializable接口或者Externalizable接口的类可以在运行时实例化,那么该方法就返回true
    • 如果可以在运行时序列化,就会调用desc.newInstance() 方法使用反射的方式调用无参构造方法新建一个对象,创建一个类的新的实例
      • 如果类实现的是Serializable接口,就调用第一个不可进行序列化超类的无参构造方法数创建新的实例
      • 如果类实现的Externalizable接口,就调用公共的无参构造方法创建新的实例
  • 因为序列化过程中会通过反射调用无参构造函数创建一个新的对象,所以序列化会破坏单例模式
  • 为了防止序列化破坏单例模式,可以在Singleton.java中添加readResolve() 方法并且指定要返回的对象的生成策略
    • 因为readOrdinaryObject() 方法源码中的hasResolveMethod() 表示如果实现了Serializable或者Externalizable接口的类中包含readResolve() 方法就返回true
    • invokeReadResolve() 方法会通过反射的方式调用要被反序列化的类的readResolve() 方法

总结

到此这篇关于Java基础入门之序列化和反序列化的文章就介绍到这了,更多相关Java序列化和反序列化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 一起学JAVA基础之运算符

    目录 1运算符 1.1概述 1.2运算符速查表 1.3练习:测试自增自减 1.4练习:测试逻辑运算符 1.5练习:求两数的最大值 1.6练习:求平年闰年 2拓展补充: 2.1总结1:算术运算符之自增自减运算符 2.2总结2:逻辑运算符 2.3总结3:优先级控制 总结 1 运算符 1.1 概述 运算符 用于连接 表达式 的 操作数,并对操作数执行运算. 例如,表达式num1+num2,其操作数是num1和num2,运算符是”+”. 在java语言中,运算符可分为5种类型: 算术运算符.赋值运算符.

  • Java栈和基础队列的实现详解

    目录 栈(stack) 栈支持的三个核心操作: 栈的常见实际应用: 栈的实现 队列 无论是哪种队列,都必须支持三个核心操作: 基础队列的实现 栈和队列:都是线性表,都是基于List基础上的实现 线性表:数组,链表,字符串,栈,队列 元素按照一条“直线”排列,线性表这个结构中,一次添加单个元素 栈(stack) 一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作.进行数据插入和删除操作的一端称为栈顶,另一端称为栈底.栈中的数据元素遵守后进先出LIFO(Last In First Out)

  • Java基础教程之整数运算

    目录 引言 溢出 自增/自减 移位运算 位运算 运算优先级 类型的自动提升与强制转型 练习 小结 总结 引言 Java的整数运算遵循四则运算规则,可以使用任意嵌套的小括号.四则运算规则和初等数学一致.例如: public class Main { public static void main(String[] args) { int i=(100+200)*(99-88);//3300 int n=7*(5+(i-9));//23072 System.out.println(i); Syste

  • java基础详细笔记之异常处理

    目录 异常概述 常见异常的举例 空指针异常NullPointerException 数组角标越界异常ArrayIndexOutOfBoundsException 异常的抛出与捕捉 抛出异常 捕捉异常 在方法中抛出异常 使用throws关键字抛出异常 使用throw关键字抛出异常(自定义异常) 异常的使用原则 总结 异常概述 在Java中,这种在程序运行时可能出现的一些错误称为异常.异常是一个在程序执行期间发生的事件,它中断了正在执行的成宿的正常指令流. 视频笔记:  Java程序执行时遇到的异常

  • JAVA基础快速从入门到精通

    目录 java程序基本结构 程序注释 变量常量 变量 常量 数据类型与类型转换 常用数据类型 类型转换 运算符表达式 标识符关键字保留字 小常识 这里是JAVA成仙之路 java程序基本结构 java程序的源码文件是Xxx.java,Xxx代码类名和文件名一致(一般要求首字母大写,从第二个单词首字母大写. 新建一个类,类名User class User{ } 新建一个User类,执行代码在控制台打印出"hello 中国"的效果 class User{ public static voi

  • Java基础知识之注解、元注解

    目录 注解 注解作用 Java预定义的注解 自定义注解 元注解 实例: 注解使用总结 总结 注解 Java注解也称Java标注,是jdk1.5(5.0)后的新特征.Java语言中的类.方法.变量.参数和包等都可以被标注.和Javadoc不同,Java注解可以通过反射获取标注内容,在编译器生成类文件时,标注可以被嵌入到字节码中,Java虚拟机可以保留标注内容,在运行时可以获取到标注内容,当然它也支持自定义Java标注 功能:用于说明程序 用途:一般用在框架中使用 格式:@AnnotationNam

  • Java实现单链表基础操作

    关于链表 链表是有序的列表链表是以节点的方式来存储每个节点包含data域,next域(指向下一个节点)分带头节点的链表和没有头节点的链表 定义一个节点: package linkedQueue; public class HeroNode { public int no; public String name; public String nickname; public HeroNode next;//指向下一个节点 public HeroNode(int no, String name, S

  • Java基础入门总结之序列化和反序列化

    目录 基本概念 序列化 反序列化 序列化和反序列化总结 自定义序列化策略 Externalizable transient 静态变量 序列化ID 破坏单例 总结 基本概念 Java中创建对象时,一旦程序终止,创建的对象可能就不存在.要想使得对象能够在程序不运行的状态下依然能够保存对象的信息,这时就需要用到序列化机制 序列化机制: 一个对象可以被表示为一个字节序列,包括: 对象的数据 对象的类型信息 存储在对象中的数据类型 将可序列化对象写入文件后,可以从文件中读取出来,根据对象的各种信息在内存中

  • Java基础之toString的序列化 匿名对象 复杂度精解

    目录 序列化 匿名对象 复杂度 时间复杂度 大O的渐进表示法 时间复杂度的分类 计算时间 复杂度的方法 空间复杂度 toString的序列化.匿名对象.复杂度 序列化 toString 方法的原理就是序列化,他可以帮助我们讲一个抽象的对象变得具体,譬如把对象里面的名字.年龄.身高等信息具象为字符串.(总之,序列化:将对象转化为字符串:反序列化:将字符串转化为对象). 匿名对象 匿名对象适用于只想使用一次的情况,因为匿名对象是没有引用的,每次用都要重新new 一遍对象,很麻烦. class Per

  • Java IO流对象的序列化和反序列化实例详解

    Java-IO流 对象的序列化和反序列化 序列化的基本操作 1.对象序列化,就是将Object转换成byte序列,反之叫对象的反序列化. 2.序列化流(ObjectOutputStream),writeObject 方法用于将对象写入输出流中: 反序列化流(ObjectInputStream),readObject 方法用于从输入流中读取对象. 3.序列化接口(Serializeable) 对象必须实现序列化接口,才能进行序列化,否则会出现异常.这个接口没有任何方法,只是一个标准. packag

  • Java基础入门 Swing中间容器的使用

    目录 Java基础入门 Swing中间容器 下面举例说明一下JScrollPane的方法 Java Swing顶层容器类 Swing拥有三个常用的顶层容器类 Java基础入门 Swing中间容器 在Swing中不仅有JFrame.JDialog这样的顶级窗口,还拥有一些中间容器,这些容器不能单独存在,必须依存在顶级窗口中.最常见的是JPanel.JScrollPane. JPanel:JPanel和AWT中的Panel组件使用方法基本一致,他是一个无边框不能被放大.移动.关闭的面板,它的默认布局

  • Java,C#使用二进制序列化、反序列化操作数据

    java使用二进制序列化.反序列化的操作首先,要引入java.io下面相关包,或者直接写import java.io.*; 下面,为了书写操作的方便,采用复制文件,和throws声明异常的方式来写 复制代码 代码如下: public void test6() throws IOException { byte[] b = new byte[1024];//定义字节数组,缓冲 FileInputStream in = new FileInputStream("E:\\logo.gif")

  • Java基础入门语法--String类

    今天带大家了解一下java的基础法语---String 字符串是我们以后工作中非常常用到的类型. 使用起来都非常简单方便, 我们一定要使用熟练. 那么C语言中是否有字符串类型? 答案是 " 没有 " !! char *p = " hello"; 那么p 的类型是一个字符串类型么? 不是,p是一个指针!! 而在 Java当中 是有 字符串类型的--String 一.定义方式 创建字符串的方式有很多种,常见的构造 String 的方式如以下: 方式一:直接赋值法 Str

  • java基础入门之IO流

    目录 io学习框架: 文件: Io流的原理: 节点流和处理流: BufferWriter: 处理字节的处理流: 标准输入和输出: 转换流: 打印流: Properties类: 总结 io学习框架: 文件: 保存数据的地方. 1)常见文件对象的相关构造器和方法: 当进行File file = new File(filePath);只是在内存上有一个文件对象: 只有file.createNewFile();才会在磁盘创建文件 获取文件的相关信息: utf8中,一个汉字是三个字节,所以当用字节流的re

  • Java基础入门篇——While循环

    循环结构分两大类,一类是当型,一类是直到型. 当型: 当布尔值表达式条件为True时,反复执行某语句,当布尔表达式的值为False时才停止循环,例如:while 与 for循环. 直到型: 先执行某语句,在判断布尔表达式,如果为true,再执行某语句,如此反复,直到布尔表达式条件为false时才停止循环,例如do - while循环. 语法结构: while (布尔表达式) { 循环体; } 一.循环结构语句 1.在我们实际生活中经常会把同一件事情重复做好几次.例如:潮汕人喜欢喝茶,只要在喝茶的

  • Java基础之序列化与反序列化详解

    目录 1.什么是序列化与反序列化? 2.Java如何实现序列化和反序列化? 3.如何自定义序列化和反序列化呢? 4.writeObject和readObject方法 5.serializable接口 1.什么是序列化与反序列化? 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程.一般将一个对象存储至一个储存媒介,例如档案或是记亿体缓冲等.在网络传输过程中,可以是字节或是XML等格式.而字节的或XML编码格式可以还原完全相等的对象.这个相反的过程又称为反序列

  • Java对象的XML序列化与反序列化实例解析

    上一篇文章我们介绍了java实现的各种排序算法代码示例,本文我们看看Java对象的xml序列化与反序列化的相关内容,具体如下. XML是一种标准的数据交换规范,可以方便地用于在应用之间交换各类数据.如果能在Java对象和XML文档之间建立某种映射,例如Java对象的XML序列化和反序列化,那么就可以使Java的对象方便地与其他应用进行交换. java.beans包里面有两个类XMLEncoder和Decoder,分别用于将符合JabaBeans规范的Java对象以XML方式序列化和反序列化.以下

随机推荐