• 【面试题】——JavaIO篇(23题)



    在这里插入图片描述
    在这里插入图片描述

    1.什么是Java IO?

    Java IO(Input/Output)是用于处理输入和输出操作的API,它允许程序与外部世界进行数据交互

    2.如何从数据传输方式理解IO流?

    可以从三个不同的维度进行分类:

    • 1、按照流的方向(输出输入都是站在程序所在内存的角度划分的)
    输入流:只能从中读取数据【主要由InputStream和Reader作为基类】

    • 输出流:只能向其写入数据【主要由outputStream和Writer作为基类】

    • 2、按照流的操作颗粒度划分

    • 字节流:以字节为单元,可操作任何数据【主要由InputStream和outPutStream作为基类】

    • 字符流:以字符为单元,只能操作纯字符数据,比较方便【主要由Reader和Writer作为基类】

    • 3、按照流的角色划分

    • 节点流:可以从/向一个特定的IO设备(如磁盘,网络)读/写数据的流,也叫【低级流,主要由】

    • 处理流:用于对一个已存在的流进行连接和封装,通过封装后的流来实现数据的读/写功能,也叫【高级流】

    3.Java IO设计上使用了什么设计模式?

    • 单一职责原则(Single Responsibility Principle): 这是一个重要的面向对象设计原则,它要求一个类应该只有一个责任。在Java IO中,不同的类负责不同的I/O操作,如InputStream负责读取字节,OutputStream负责写入字节,这符合单一职责原则。
    • 装饰器模式(Decorator Pattern): Java IO中的缓冲流(如BufferedReader和BufferedWriter)以及过滤流(如GZIPInputStream和GZIPOutputStream)采用了装饰器模式。这些类通过组合来增强I/O流的功能,而不是通过继承来扩展。
    BufferedReader br = new BufferedReader(new FileReader("file.txt"));
    
    • 1

    这里,BufferedReader装饰了FileReader,以提供缓冲读取的功能。

    • 策略模式(Strategy Pattern): Java IO库中的Charset和CharsetEncoder/CharsetDecoder类采用了策略模式。它们允许你根据不同的字符编码策略来进行字符编码和解码。
    Charset utf8 = Charset.forName("UTF-8");
    CharsetEncoder encoder = utf8.newEncoder();
    
    • 1
    • 2

    这里,Charset对象充当策略对象,CharsetEncoder则根据不同的策略来执行编码操作。

    • 观察者模式(Observer Pattern): Java IO库中的File和DirectoryStream等类可用于监视文件系统中的文件和目录。这些类允许你注册观察者来监听文件系统事件,符合观察者模式。
    Path directory = Paths.get("my_directory");
    WatchService watchService = FileSystems.getDefault().newWatchService();
    directory.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
    
    
    • 1
    • 2
    • 3
    • 4

    这里,WatchService充当观察者,监视文件系统中文件的创建事件。

    4.什么是Java NIO?

    Java NIO : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。

    5.什么时BIO?

    Java BIO : 同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。

    6.什么是AIO?

    Java AIO(NIO.2) : 异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。

    7.你怎么理解同步IO和异步IO?

    • 同步I/O(Synchronous I/O):
      阻塞模式: 在同步I/O中,当一个I/O操作被发起时,调用线程将被阻塞,直到操作完成或出错为止。这意味着线程会一直等待,无法执行其他任务。
      顺序执行: 同步I/O操作通常是按照它们的发起顺序依次执行的。每个操作必须等待前一个操作完成才能继续执行。
      资源占用: 同步I/O需要分配一个线程来处理每个I/O操作,如果有大量并发连接,将消耗大量线程资源。

    • 异步I/O(Asynchronous I/O):
      非阻塞模式: 在异步I/O中,当一个I/O操作被发起后,调用线程不会被阻塞,可以继续执行其他任务,不必等待操作完成。
      并发性: 异步I/O允许同时发起多个I/O操作,并在后台进行处理,因此具有更高的并发性。
      回调机制: 异步I/O通常使用回调函数来处理I/O操作完成的通知。当I/O操作完成时,系统会调用预先注册的回调函数,而不是等待线程。
      复杂性: 异步I/O编程相对更复杂,因为它需要处理回调函数、状态管理等复杂性问题。

    8.你怎么理解阻塞IO和非阻塞IO?

    阻塞IO:当一个线程执行I/O操作时,它将一直阻塞该线程被一直占用,直到操作完成。
    非阻塞IO:调用线程不会被阻塞,可以继续执行其他任务,不必等待操作完成。允许一个线程管理多个通道(连接)。

    9.IO中的输入流和输出流有什么区别?

    10.字节流和字符流的区别?

    答:读字节流时,读一个字节后返回一个字节;字节流使用字节流读取一个或多个字节(中文对应的字节数为两个,在 UTF-8 码表中是 3 字节)时间。首先检查指定的编码表,并返回找到的字符。字节流可以处理图片、MP3、AVI视频文件等各种类型的数据,而字符流只能处理字符数据。除了字节流,只要是处理纯文本数据,就要优先使用字符流。字节流主要是操作 byte 类型数据,以 byte 以数组为准,主要操作类别为 OutputStream、Inputstream字符流处理的单元是 2 个字节的 Unicode 字符分别操作字符、字符数组或字符串,字节流处理单元为 1 操作字节和字节数组的字节。因此,字符流是由 Java 将字节转换为虚拟机 2 个字节的 Unicode 字符是单位字符制成的,所以对多国语言有很好的支持!如果是音频文件、图片和歌曲,最好使用字节流。如果与中文(文本)有关,最好使用字符流。在程序中,一个字符等于两个字节,java 提供了 Reader、Writer 两个专门操作字符流的类别。

    11.Java 流量有多少种类型?

    答:
    (1)按流量方向:输入流(inputStream)和输出流(outputStream);
    (2)按实现功能划分:节点流(可以从或到特定的地方(节点)读写数据。如 FileReader)和处理流(是对现有流的连接和封装,通过封装流的功能调用实现数据读写。如 BufferedReader。处理流的结构方法总是以其他流对象为参数。一个流对象通过其他流多次包装,称为流链接);
    (3)按处理数据的单位: 字节流和字符流。继承字节流 InputStream 和 OutputStrea,InputStreamreader继承字符流 和 OutputStreamWriter 。

    12.如何将字节流转化为字符流?

    答:字节输入流通字符输入流通 InputStreamReader 这种结构函数可以实现并传输 InputStream 对象。
    字节输出流字符输出流通过 OutputStreamWriter 这种结构函数可以实现并传输 OutputStream 对象。

    13.如何将一个 java 将对象序列化到文件中?

    答:在 java 能够序列化的类必须先实现 Serializable 接口,没有抽象的方法,只是起到了标记作用。

      public class Test {
            public static void main(String[] args) throws Exception {
                // 对象输出流
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(new File("D://obj")));
                objectOutputStream.writeObject(new User("zhangsan", 100));
                objectOutputStream.close();
                // 对象输入流
                ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(new File("D://obj")));
                User user = (User) objectInputStream.readObject();
                System.out.println(user);
                objectInputStream.close();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    14.什么是 java序列化?

    答:序列化是一种处理对象流的机制。所谓对象流,就是流化对象的内容。流化后的对象可以读写,也可以在网络之间传输。序列化是为了解决对象流读写操作中引起的问题。

    15.如何实现 java 序列化?

    答:实现序列化将需要实现序列化类Serializable 界面,界面没有实现的方法,implements Serializable 只是为了标记对象可以序列化,然后使用输出流(如:File Output Stream)来构造一个 Object Output Stream(对象流)对象,然后,使用 Object Output Stream 对象的 write Object(Object obj)该方法可以将参数为 obj 对象写出(即保存其状态),如果要恢复,则使用输入流。

    16.Filter流是什么?

    答:Filter Stream是IO流的主要功能,用于为存在的流量增加一些额外的功能,如向目标文件添加源文件中不存在的行数或复制性能。

    17.Filter流有哪些可用?

    答:在http://java.主要由四个可用的filter包组成 Stream。两个字节filter stream,两个字符filter stream. 分别是Filter Input Stream, Filter Output Stream, Filter Reader and Filter Writer.这些类别是抽象的,不能实例化。

    18.解释java.io.Serializable接口?

    答:通过实现类 java.io.Serializable 该接口可以启用其序列化功能。未实现此接口的类别将无法使其任何状态序列化或反序列化。

    19.如何实现对象克隆?

    答:有两种方式(1)实现 Cloneable 接口并重写 Object 类中的 clone()方法(2)实现 Serializable 接口可以通过对象的序列化和反序列化来实现真正的深度克隆。

    20.Java中的输入流和输出流有什么区别?

    输入流用于从数据源(如文件或网络)读取数据,输出流用于向目标(如文件或网络)写入数据。

    21.Java中有几种类型的流?

    分为字符流和字节流。

    22.如何从数据操作上理解IO流?

    在这里插入图片描述

    23.BIO、NIO、AIO三者区别以及适用场景?

    • BIO(Blocking I/O):
      阻塞模型: BIO是基于阻塞模型的I/O操作,意味着当一个线程执行I/O操作时,它将一直阻塞,直到操作完成。
      同步性: 在BIO中,所有I/O操作都是同步的,一个线程对一个连接进行读或写,直到完成。
      适用性: 适用于连接数量较少且每个连接的数据交互频繁的情况,但在高并发环境下性能不佳。

    • NIO(Non-blocking I/O):
      非阻塞模型: NIO采用了非阻塞模型,允许一个线程管理多个通道(连接)。
      选择器(Selector): NIO引入了选择器(Selector)的概念,通过选择器一个线程可以监听多个通道上的事件,如读就绪、写就绪等。
      缓冲区(Buffer): NIO使用缓冲区来存储数据,可以提高I/O效率。
      适用性: 适用于需要处理大量连接且连接数较多,但每个连接的数据交互相对较少的情况,如Web服务器。

    • AIO(Asynchronous I/O):
      异步模型: AIO采用异步模型,允许一个线程在进行I/O操作时不被阻塞,当操作完成后会通知应用程序。
      回调机制: AIO使用回调机制来处理I/O操作完成的通知。
      适用性: 适用于需要处理大量连接且每个连接的数据交互较少,且希望充分利用CPU的多核性能的情况。

    • 总结各种I/O模型的适用场景:
      BIO适用于连接数较少,且每个连接的数据交互频繁的情况,但不适用于高并发环境。
      NIO适用于需要处理大量连接,但每个连接的数据交互相对较少的情况,具有更好的性能和资源利用率。
      AIO适用于需要处理大量连接,且每个连接的数据交互较少,同时希望充分利用CPU多核性能的情况。
      选择适当的I/O模型取决于应用程序的特性和需求,不同的模型提供了不同的性能和可伸缩性。

  • 相关阅读:
    Redis系列8:Bitmap实现亿万级数据计算
    SCS【7】单细胞转录组之轨迹分析 (Monocle 3) 聚类、分类和计数细胞
    Unity的BuildPlayerProcessor:深入解析与实用案例
    Android 弹幕功能实现
    Jvm类加载机制
    Spring Boot 3 集成 Knife4j
    java计算机毕业设计springboot+vue废弃资源回收系统
    vuex是什么?如何使用?使用他的功能场景?
    M1/M2 Parallels Desktop 19虚拟机安装Windows11教程(超详细)
    SpringBoot引入外部jar包,项目打包成war包发布(亲测有效) - 第453篇
  • 原文地址:https://blog.csdn.net/qq_42785250/article/details/132973244