当前位置: 首页 > article >正文

Java基础关键_027_IO流(五)

目  录

一、装饰器设计模式

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.实例

/**
 * 接口
 */
public interface Eatable {
    void eat();
}
/**
 * 所有装饰者的父类
 */
public abstract class EatableDec implements Eatable {
    protected Eatable eatable;

    public EatableDec(Eatable eatable) {
        this.eatable = eatable;
    }

    @Override
    public void eat() {

    }
}
/**
 * 装饰者1
 */
public class DoDec extends EatableDec {

    public DoDec(Eatable eatable) {
        super(eatable);
    }

    @Override
    public void eat() {
        System.out.println(eatable + "开始吃饭!");
        super.eat();
        System.out.println(eatable + "吃饭结束!");
    }
}
/**
 * 装饰者2
 */
public class TimeDec extends EatableDec {
    public TimeDec(Eatable eatable) {
        super(eatable);
    }

    @Override
    public 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();
    }
}
/**
 * 被装饰者1
 */
public class Man implements Eatable{
    @Override
    public void eat() {
        System.out.println("Man eat");
    }
}
/**
 * 被装饰者2
 */
public class Woman implements Eatable {
    @Override
    public void eat() {
        System.out.println("Woman eat");
    }
}
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

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

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.实例 

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.对象流装饰字节数组

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

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());   // 1
            System.out.println(objectInputStream.readChar());   // a
            System.out.println(objectInputStream.readShort());  // 100
            System.out.println(objectInputStream.readInt());    // 6666
            System.out.println(objectInputStream.readLong());   // 99999
            System.out.println(objectInputStream.readFloat());  // 1.1
            System.out.println(objectInputStream.readDouble()); // 2.2
            System.out.println(objectInputStream.readBoolean());    // true
            System.out.println(objectInputStream.readObject()); // hello
            
            byteArrayInputStream.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 对象写到内存中的字节数组,再从内存中的字节数组读取,读取到的对象就是一个深克隆。

public class Student implements Serializable {
    @Serial
    private 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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public 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);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
public class Teacher implements Serializable {
    @Serial
    private 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;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                ", student=" + student +
                '}';
    }
}
/**
 * 利用 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.kler.cn/a/594966.html

相关文章:

  • 软考-软件设计师-程序设计语言
  • 数据结构——顺序栈seq_stack
  • 力扣刷题——143.重排链表
  • 多数据源@DS和@Transactional踩坑之路
  • 【负载均衡系列】Nginx
  • 到底爱不爱我
  • stm32-定时器
  • GITLAB部署安装教程
  • JNI介绍
  • 算法及数据结构系列 - 二分查找
  • 游戏引擎学习第172天
  • 深度解析历年蓝桥杯算法题,助力提升编程技能
  • Saga 模式实战 Demo
  • Compose 实践与探索十五 —— 自定义触摸
  • Prometheus Exporter系列-Postgres_Exporter一键部署
  • Java 大视界 -- Java 大数据分布式计算中的通信优化与网络拓扑设计(145)
  • Python 单例模式的 5 种实现方式:深入解析与最佳实践
  • 如何给商品一键换色?图生生AI,告别繁琐修图
  • 【Dify平台】Function Call 模式模式和ReAct模型有什么不同?
  • Compose 实践与探索十六 —— 与传统的 View 系统混用