Java基础关键_027_IO流(五)

devtools/2025/4/1 5:44:33/

目  录

一、装饰器设计模式

1.说明

2.实例

3.实例类图 

 二、压缩流

1.GZipOutputStream

2.GZipInputStream

 三、字节数组流

1.说明

2.实例 

3.对象流装饰字节数组

四、对象克隆

1.clone() 的克隆

2.序列化和反序列化的克隆

3.字节数组流的深克隆


一、装饰器设计模式

1.说明

  1. 23 种设计模式之一,属于结构型设计模式;
  2. 通过编写大量子类来继承父类,重写父类中的方法,会导致子类数量翻倍,即类爆炸;
  3. 装饰器模式可以在不修改原代码的基础上完成功能扩展,符合 OCP 原则,避免了继承所带来的类爆炸问题;
  4. IO 流中大量使用了装饰器模式;
  5. 角色:
    1. 组件:定义一个对象接口,可以给这些对象动态地添加职责。它是被装饰者和装饰者共同实现的接口。
    2. 具体组件:实现了组件接口,是被装饰的原始对象,定义了基本的行为。
    3. 装饰器:持有一个组件对象的引用,并实现了组件接口。它的主要作用是为具体组件添加额外的功能。
    4. 具体装饰器:具体实现装饰器,负责向组件添加具体的额外功能。
  6. 装饰者和被装饰者应当实现相同接口 / 抽象类;
  7. 装饰者应含有被装饰者的引用,引用类型应该是抽象的、不是具体的。

2.实例

java">/*** 接口*/
public interface Eatable {void eat();
}
java">/*** 所有装饰者的父类*/
public abstract class EatableDec implements Eatable {protected Eatable eatable;public EatableDec(Eatable eatable) {this.eatable = eatable;}@Overridepublic void eat() {}
}
java">/*** 装饰者1*/
public class DoDec extends EatableDec {public DoDec(Eatable eatable) {super(eatable);}@Overridepublic void eat() {System.out.println(eatable + "开始吃饭!");super.eat();System.out.println(eatable + "吃饭结束!");}
}
java">/*** 装饰者2*/
public class TimeDec extends EatableDec {public TimeDec(Eatable eatable) {super(eatable);}@Overridepublic void eat() {Date now = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println(sdf.format(now) + eatable + "开始吃饭!");super.eat();}
}
java">/*** 被装饰者1*/
public class Man implements Eatable{@Overridepublic void eat() {System.out.println("Man eat");}
}
java">/*** 被装饰者2*/
public class Woman implements Eatable {@Overridepublic void eat() {System.out.println("Woman eat");}
}
java">public class Test {public static void main(String[] args) {Eatable e1 = new DoDec(new Man());Eatable e3 = new TimeDec(new Man());Eatable e2 = new DoDec(new Woman());Eatable e4 = new TimeDec(new Woman());e1.eat();e3.eat();e2.eat();e4.eat();}
}


3.实例类图 


 二、压缩流

1.GZipOutputStream

java">public class GZipOutputStreamTest {public static void main(String[] args) {try (FileInputStream fileInputStream = new FileInputStream("D:\\Test.txt");GZIPOutputStream gzipOutputStream = new GZIPOutputStream(new FileOutputStream("D:\\Test.txt.gz"))) {byte[] bytes = new byte[1024];int readCount = 0;while ((readCount = fileInputStream.read(bytes)) != -1) {gzipOutputStream.write(bytes, 0, readCount);}} catch (IOException e) {throw new RuntimeException(e);}}
}

 


2.GZipInputStream

java">public class GZipInputStreamTest {public static void main(String[] args) {try (GZIPInputStream gzipInputStream = new GZIPInputStream(new FileInputStream("D:\\Test.txt.gz"));FileOutputStream fileOutputStream = new FileOutputStream("D:\\Java\\Test.txt")) {byte[] bytes = new byte[1024];int readCount = 0;while ((readCount = gzipInputStream.read(bytes)) != -1) {fileOutputStream.write(bytes, 0, readCount);}} catch (FileNotFoundException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}
}

 


 三、字节数组流

1.说明

  1. 字节数组流是内存流;
  2. ByteArrayInputStream 和 ByteArrayOutputStream 都是内存操作流,无需 打开 / 关闭 文件等操作,能够方便地读写字节数组、图像数据等内存中的数据;
  3. ByteArrayInputStream 和 ByteArrayOutputStream 都是节点流。

2.实例 

java">public class ByteArrayOutputStreamTest {public static void main(String[] args) {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();byteArrayOutputStream.write(97);byteArrayOutputStream.write(98);byteArrayOutputStream.write(99);byteArrayOutputStream.write(100);byteArrayOutputStream.write(101);byte[] byteArray = byteArrayOutputStream.toByteArray();for (byte b : byteArray) {System.out.print(b + "\t");}// 97	98	99	100	101}
}

3.对象流装饰字节数组

        注意:由于包装流有缓存,所以使用包装流就要手动刷新。

java">public class ByteArrayOutputStreamTest {public static void main(String[] args) {try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) {objectOutputStream.writeByte(1);objectOutputStream.writeChar('a');objectOutputStream.writeShort(100);objectOutputStream.writeInt(6666);objectOutputStream.writeLong(99999);objectOutputStream.writeFloat(1.1f);objectOutputStream.writeDouble(2.2);objectOutputStream.writeBoolean(true);objectOutputStream.writeObject("hello");objectOutputStream.flush();byte[] byteArray = byteArrayOutputStream.toByteArray();ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);System.out.println(objectInputStream.readByte());   // 1System.out.println(objectInputStream.readChar());   // aSystem.out.println(objectInputStream.readShort());  // 100System.out.println(objectInputStream.readInt());    // 6666System.out.println(objectInputStream.readLong());   // 99999System.out.println(objectInputStream.readFloat());  // 1.1System.out.println(objectInputStream.readDouble()); // 2.2System.out.println(objectInputStream.readBoolean());    // trueSystem.out.println(objectInputStream.readObject()); // hellobyteArrayInputStream.close();objectInputStream.close();} catch (IOException e) {throw new RuntimeException(e);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}
}

四、对象克隆

1.clone() 的克隆

        之前在面向对象章节谈过的一种克隆方式,调用 Object 的 clone 方法默认是浅克隆,深克隆需要重写 clone 方法。参考链接如下:

Java基础关键_007_面向对象(二)https://mp.csdn.net/mp_blog/creation/editor/145369813


2.序列化和反序列化的克隆

        在第三节谈到的序列化和反序列化也可以完成对象的克隆。参考链接如下:

Java基础关键_025_IO流(三)https://mp.csdn.net/mp_blog/creation/editor/146349119 


3.字节数组流的深克隆

        将要克隆的 Java 对象写到内存中的字节数组,再从内存中的字节数组读取,读取到的对象就是一个深克隆。

java">public class Student implements Serializable {@Serialprivate static final long serialVersionUID = 1L;private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return age == student.age && Objects.equals(name, student.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}
}
java">public class Teacher implements Serializable {@Serialprivate static final long serialVersionUID = 0L;private String name;private Student student;public Teacher(String name, Student student) {this.name = name;this.student = student;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Student getStudent() {return student;}public void setStudent(Student student) {this.student = student;}@Overridepublic String toString() {return "Teacher{" +"name='" + name + '\'' +", student=" + student +'}';}
}
java">/*** 利用 ByteArrayOutputStream 和 ByteArrayInputStream 实现深拷贝*/
public class BAOISClone {public static void main(String[] args) {Teacher teacher = new Teacher("鬼谷子", new Student("孙膑", 18));try (ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(baos)) {oos.writeObject(teacher);oos.flush();byte[] byteArray = baos.toByteArray();ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);ObjectInputStream ois = new ObjectInputStream(bais);Teacher teacherClone = (Teacher) ois.readObject();System.out.println("原teacher:" + teacher);System.out.println("克隆teacher" + teacherClone);System.out.println("=====================================");teacherClone.setName("孔子");teacherClone.getStudent().setName("颜回");teacherClone.getStudent().setAge(20);System.out.println("原teacher:" + teacher);System.out.println("克隆teacher" + teacherClone);} catch (IOException e) {throw new RuntimeException(e);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}
}


http://www.ppmy.cn/devtools/171205.html

相关文章

Idea中使用Git插件_合并当前分支到master分支_冲突解决_很简单---Git工作笔记005

由于之前用svn习惯了,用的git少,其实在idea中使用git,解决冲突,合并分支,非常的简单,一起来看一下吧. 一定要注意操作之前,一定要确保自己的分支代码,都已经commit提交了,并且push到远程了. 不要丢东西. 可以看到首先,在idea的左下角有个 git,点开以后 可以看到有显示的分支…

嵌入式硬件篇---蓝牙模块

文章目录 前言一、核心技术原理蓝牙工作流程设备发现阶段配对连接阶段数据传输阶段 二、协议栈架构(以BLE为例)1.物理层2.链路层3.HCI层4.GATT 三、典型应用场景扩展1. 室内定位系统(蓝牙5.1)2. 运动健康监测3. 工业控制 四、ESP3…

VBA-Excel

VBA 一、数据类型与变量 常用数据类型: Byte:字节型,0~255。Integer:整数型,用于存储整数值,范围 -32768 到 32767。Long:长整型,可存储更大范围的整数,范围 -214748364…

军事级加密通信系统——基于QML的战术地图加密传输

目录 基于QML的战术地图加密传输一、引言二、理论背景与安全需求2.1 战术地图数据的敏感性与安全性要求2.2 QML与PyQt5集成优势2.3 加密算法与数据传输模型三、系统架构与数据流图四、QML前端界面设计与交互功能4.1 QML界面优势与设计理念4.2 功能要求4.3 QML文件示例五、加密传…

mysql 磐维(opengauss)tidb误删数据之高级恢复

Mysql参考: Mysql 8.0 XtraBackupMysqlbinlog 完全恢复 - 墨天轮 Mysql 8.0 XtraBackupMysqlbinlog 完全恢复[TOC]# 一、安装mysql 8.0.19## 1.1https://www.modb.pro/db/509223MySQL 的全量备份、增量备份与 Binlog 时间点恢复_mysqlbinlog自动备份吗-CSDN博客文章…

【python】11. 输入输出

11. 输入输出 Python两种输出值的方式: 表达式语句和 print() 函数。 第三种方式是使用文件对象的 write() 方法,标准输出文件可以用 sys.stdout 引用。 如果你希望输出的形式更加多样,可以使用 str.format() 函数来格式化输出值。 如果你希望将输出…

【STM32】SPI通信协议W25Q64Flash存储器芯片(学习笔记)

通信接口部分有介绍SPI:【STM32】USART串口协议&串口外设-学习笔记-CSDN博客 SPI通信协议 SPI通信 SPI(Serial Peripheral Interface)是由Motorola公司开发的一种通用数据总线四根通信线:SCK(Serial Clock&…

基础算法01——二分查找(Binary Search)

二分查找(Binary Search) 二分查找算法:也称为折半查找,是一种在有序数组中查找特定元素的高效算法。算法逻辑: 每次取中间位置的值与待查关键字比较: 如果待查关键字比中间位置的值小,则在有序…