0

0

Java 对象序列化 NIO NIO2详解

高洛峰

高洛峰

发布时间:2017-02-27 15:43:46

|

1565人浏览过

|

来源于php中文网

原创

java 对象序列化 nio nio2详细介绍及解析

概要:

对象序列化

对象序列化机制允许把内存中的Java对象转换成与平台无关的二进制流,从而可以保存到磁盘或者进行网络传输,其它程序获得这个二进制流后可以将其恢复成原来的Java对象。 序列化机制可以使对象可以脱离程序的运行而对立存在

序列化的含义和意义

立即学习Java免费学习笔记(深入)”;

序列化

序列化机制可以使对象可以脱离程序的运行而对立存在

序列化(Serialize)指将一个java对象写入IO流中,与此对应的是,对象的反序列化(Deserialize)则指从IO流中恢复该java对象

如果需要让某个对象可以支持序列化机制,必须让它的类是可序列化(serializable),为了让某个类可序列化的,必须实现如下两个接口之一:

  • Serializable:标记接口,实现该接口无须实现任何方法,只是表明该类的实例是可序列化的

  • Externalizable

所有在网络上传输的对象都应该是可序列化的,否则将会出现异常;所有需要保存到磁盘里的对象的类都必须可序列化;程序创建的每个JavaBean类都实现Serializable;

使用对象流实现序列化

实现Serializable实现序列化的类,程序可以通过如下两个步骤来序列化该对象:

1.创建一个ObjectOutputStream,这个输出流是一个处理流,所以必须建立在其他节点流的基础之上

// 创建个ObjectOutputStream输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"));

2.调用ObjectOutputStream对象的writeObject方法输出可序列化对象

// 将一个Person对象输出到输出流中
oos.writeObject(per);

定义一个NbaPlayer类,实现Serializable接口,该接口标识该类的对象是可序列化的

public class NbaPlayer implements java.io.Serializable
{
  private String name;
  private int number;
  // 注意此处没有提供无参数的构造器!
  public NbaPlayer(String name, int number)
  {
    System.out.println("有参数的构造器");
    this.name = name;
    this.number = number;
  }

  // name的setter和getter方法
  public void setName(String name)
  {
    this.name = name;
  }
  public String getName()
  {
    return this.name;
  }

  // number的setter和getter方法
  public void setNumber(int number)
  {
    this.number = number;
  }
  public int getNumber()
  {
    return this.number;
  }
}

使用ObjectOutputStream将一个NbaPlayer对象写入磁盘文件

import java.io.*;

public class WriteObject
{
  public static void main(String[] args)
  {
    try(
      // 创建一个ObjectOutputStream输出流
      ObjectOutputStream oos = new ObjectOutputStream(
        new FileOutputStream("object.txt")))
    {
      NbaPlayer player = new NbaPlayer("维斯布鲁克", 0);
      // 将player对象写入输出流
      oos.writeObject(player);
    }
    catch (IOException ex)
    {
      ex.printStackTrace();
    }
  }
}

反序列化

从二进制流中恢复Java对象,则需要使用反序列化,程序可以通过如下两个步骤来序列化该对象:

GoEnhance
GoEnhance

全能AI视频制作平台:通过GoEnhance AI让视频创作变得比以往任何时候都更简单。

下载

1.创建一个ObjectInputStream输入流,这个输入流是一个处理流,所以必须建立在其他节点流的基础之上

// 创建个ObjectInputStream输出流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.txt"));

2.调用ObjectInputStream对象的readObject()方法读取流中的对象,该方法返回一个Object类型的Java对象,可进行强制类型转换成其真实的类型

// 从输入流中读取一个Java对象,并将其强制类型转换为Person类
Person p = (Person)ois.readObject();

从object.txt文件中读取NbaPlayer对象的步骤

import java.io.*;
public class ReadObject
{
  public static void main(String[] args)
  {
    try(
      // 创建一个ObjectInputStream输入流
      ObjectInputStream ois = new ObjectInputStream(
        new FileInputStream("object.txt")))
    {
      // 从输入流中读取一个Java对象,并将其强制类型转换为NbaPlayer类
      NbaPlayer player = (NbaPlayer)ois.readObject();
      System.out.println("名字为:" + player.getName()
        + "\n号码为:" + player.getNumber());
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }
}

反序列化读取的仅仅是Java对象的数据,而不是Java类,因此采用反序列化恢复Java对象时,必须提供Java对象所属的class文件,否则会引发ClassNotFoundException异常;反序列化机制无须通过构造器来初始化Java对象

如果使用序列化机制向文件中写入了多个Java对象,使用反序列化机制恢复对象必须按照实际写入的顺序读取。当一个可序列化类有多个父类时(包括直接父类和间接父类),这些父类要么有无参的构造器,要么也是可序列化的—否则反序列化将抛出InvalidClassException异常。如果父类是不可序列化的,只是带有无参数的构造器,则该父类定义的Field值不会被序列化到二进制流中

对象引用的序列化

如果某个类的Field类型不是基本类型或者String类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则有用该类型的Field的类也是不可序列化的

public class AllStar implements java.io.Serializable
{
  private String name;
  private NbaPlayer player;
  public AllStar(String name, NbaPlayer player)
  {
    this.name = name;
    this.player = player;
  }
  // 此处省略了name和player的setter和getter方法

  // name的setter和getter方法
  public String getName()
  {
    return this.name;
  }

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

  // player的setter和getter方法
  public NbaPlayer getPlayer() 
  {
    return player;
  }

  public void setPlayer(NbaPlayer player) 
  {
    this.player = player;
  }
}

Java特殊的序列化算法

  • 所有保存到磁盘中的对象都有一个序列化编号

  • 当程序试图序列化一个对象时,程序将先检查该对象是否已经被序列化过,只有该对象从未(在本次虚拟中机)被序列化过,系统才会将该对象转换成字节序列并输出

  • 如果某个对象已经序列化过,程序将只是直接输出一个序列化编号,而不是再次重新序列化该对象

import java.io.*;
public class WriteAllStar
{
  public static void main(String[] args)
  {
    try(
      // 创建一个ObjectOutputStream输出流
      ObjectOutputStream oos = new ObjectOutputStream(
        new FileOutputStream("allStar.txt")))
    {
      NbaPlayer player = new NbaPlayer("詹姆斯哈登", 13);
      AllStar allStar1 = new AllStar("西部全明星", player);
      AllStar allStar2 = new AllStar("首发后卫", player);
      // 依次将四个对象写入输出流
      oos.writeObject(allStar1);
      oos.writeObject(allStar2);
      oos.writeObject(player);
      oos.writeObject(allStar2);
    }
    catch (IOException ex)
    {
      ex.printStackTrace();
    }
  }
}

4个写入输出流的对象,实际上只序列化了3个,而且序列的两个AllStar对象的player引用实际是同一个NbaPlayer对象。以下程序读取序列化文件中的对象

import java.io.*;
public class ReadAllStar
{
  public static void main(String[] args)
  {
    try(
      // 创建一个ObjectInputStream输出流
      ObjectInputStream ois = new ObjectInputStream(
        new FileInputStream("allStar.txt")))
    {
      // 依次读取ObjectInputStream输入流中的四个对象
      AllStar star1 = (AllStar)ois.readObject();
      AllStar star2 = (AllStar)ois.readObject();
      NbaPlayer player = (NbaPlayer)ois.readObject();
      AllStar star3 = (AllStar)ois.readObject();
      // 输出true
      System.out.println("star1的player引用和player是否相同:"
        + (star1.getPlayer() == player));
      // 输出true
      System.out.println("star2的player引用和player是否相同:"
        + (star2.getPlayer() == player));
      // 输出true
      System.out.println("star2和star3是否是同一个对象:"
        + (star2 == star3));
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }
}

如果多次序列化同一个可变Java对象时,只有第一次序列化时才会把该Java对象转换成字节序列并输出

当使用Java序列化机制序列化可变对象时,只有第一次调用WriteObject()方法来输出对象时才会将对象转换成字节序列,并写入到ObjectOutputStream;即使在后面程序中,该对象的实例变量发生了改变,再次调用WriteObject()方法输出该对象时,改变后的实例变量也不会被输出

import java.io.*;

public class SerializeMutable
{
  public static void main(String[] args)
  {

    try(
      // 创建一个ObjectOutputStream输入流
      ObjectOutputStream oos = new ObjectOutputStream(
        new FileOutputStream("mutable.txt"));
      // 创建一个ObjectInputStream输入流
      ObjectInputStream ois = new ObjectInputStream(
        new FileInputStream("mutable.txt")))
    {
      NbaPlayer player = new NbaPlayer("斯蒂芬库里", 30);
      // 系统会player对象转换字节序列并输出
      oos.writeObject(player);
      // 改变per对象的name实例变量
      player.setName("塞斯库里");
      // 系统只是输出序列化编号,所以改变后的name不会被序列化
      oos.writeObject(player);
      NbaPlayer player1 = (NbaPlayer)ois.readObject();  //①
      NbaPlayer player2 = (NbaPlayer)ois.readObject();  //②
      // 下面输出true,即反序列化后player1等于player2
      System.out.println(player1 == player2);
      // 下面依然看到输出"斯蒂芬库里",即改变后的实例变量没有被序列化
      System.out.println(player2.getName());
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }
}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

更多Java 对象序列化 NIO NIO2详解相关文章请关注PHP中文网!

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
go语言 注释编码
go语言 注释编码

本专题整合了go语言注释、注释规范等等内容,阅读专题下面的文章了解更多详细内容。

32

2026.01.31

go语言 math包
go语言 math包

本专题整合了go语言math包相关内容,阅读专题下面的文章了解更多详细内容。

23

2026.01.31

go语言输入函数
go语言输入函数

本专题整合了go语言输入相关教程内容,阅读专题下面的文章了解更多详细内容。

16

2026.01.31

golang 循环遍历
golang 循环遍历

本专题整合了golang循环遍历相关教程,阅读专题下面的文章了解更多详细内容。

5

2026.01.31

Golang人工智能合集
Golang人工智能合集

本专题整合了Golang人工智能相关内容,阅读专题下面的文章了解更多详细内容。

6

2026.01.31

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

268

2026.01.31

高干文在线阅读网站大全
高干文在线阅读网站大全

汇集热门1v1高干文免费阅读资源,涵盖都市言情、京味大院、军旅高干等经典题材,情节紧凑、人物鲜明。阅读专题下面的文章了解更多详细内容。

195

2026.01.31

无需付费的漫画app大全
无需付费的漫画app大全

想找真正免费又无套路的漫画App?本合集精选多款永久免费、资源丰富、无广告干扰的优质漫画应用,涵盖国漫、日漫、韩漫及经典老番,满足各类阅读需求。阅读专题下面的文章了解更多详细内容。

170

2026.01.31

漫画免费在线观看地址大全
漫画免费在线观看地址大全

想找免费又资源丰富的漫画网站?本合集精选2025-2026年热门平台,涵盖国漫、日漫、韩漫等多类型作品,支持高清流畅阅读与离线缓存。阅读专题下面的文章了解更多详细内容。

85

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
FastJson教程手册
FastJson教程手册

共25课时 | 18.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号