2025 Java NIO 面试题 (精选90题) 1~30
1. 什么是Java NIO?
Java NIO(New Input/Output)是Java 1.4引入的一套新的I/O API,提供了与标准Java I/O不同的I/O处理方式。它支持面向缓冲区的、基于通道的I/O操作,提供了更高的性能和更灵活的I/O操作方式。
2. Java NIO与传统的IO有什么区别?
- 面向流 vs 面向缓冲区:传统IO是面向流的,而NIO是面向缓冲区的。
- 阻塞 vs 非阻塞:传统IO是阻塞的,而NIO支持非阻塞模式。
- 选择器:NIO引入了选择器(Selector),允许一个线程处理多个通道,提高了并发性能。
3. Java NIO的核心组件有哪些?
Java NIO的核心组件包括:
- 通道(Channel):用于数据的读写。
- 缓冲区(Buffer):用于存储数据。
- 选择器(Selector):用于多路复用,允许一个线程处理多个通道。
4. 什么是通道(Channel)?
通道(Channel)是Java NIO中的一个抽象类,用于数据的读写操作。它类似于流,但支持双向读写,并且可以与缓冲区配合使用。常见的通道实现包括FileChannel、SocketChannel、ServerSocketChannel和DatagramChannel。
5. 什么是缓冲区(Buffer)?
缓冲区(Buffer)是Java NIO中用于存储数据的容器。它是一个线性、有限的数据集合,可以存储各种数据类型(如字节、字符、整数等)。缓冲区的主要属性包括容量(Capacity)、位置(Position)、限制(Limit)和标记(Mark)。
6. 什么是选择器(Selector)?
选择器(Selector)是Java NIO中的一个类,用于实现多路复用I/O。它允许一个线程监控多个通道的I/O事件(如读、写、连接等),从而在一个线程中处理多个通道的I/O操作,提高了并发性能。
7. 缓冲区(Buffer)的基本属性有哪些?
缓冲区(Buffer)的基本属性包括:
- 容量(Capacity):缓冲区可以存储的最大数据量。
- 位置(Position):当前读写操作的位置。
- 限制(Limit):缓冲区中可以读写的数据的上限。
- 标记(Mark):一个备忘位置,可以通过reset()方法回到这个位置。
8. Buffer的容量(Capacity)、位置(Position)、限制(Limit)和标记(Mark)分别是什么?
- 容量(Capacity):缓冲区可以存储的最大数据量,一旦创建,容量不可改变。
- 位置(Position):当前读写操作的位置,每次读写操作后,位置会自动增加。
- 限制(Limit):缓冲区中可以读写的数据的上限,不能超过容量。
- 标记(Mark):一个备忘位置,可以通过mark()方法设置,通过reset()方法回到这个位置。
9. 如何创建一个Buffer?
可以通过Buffer的静态方法创建不同类型的缓冲区,例如:
// 创建一个容量为1024字节的字节缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 创建一个容量为1024字符的字符缓冲区
CharBuffer charBuffer = CharBuffer.allocate(1024);
10. Buffer有哪些类型?
Java NIO提供了多种类型的缓冲区,包括:
- ByteBuffer:用于存储字节数据。
- CharBuffer:用于存储字符数据。
- ShortBuffer:用于存储短整型数据。
- IntBuffer:用于存储整型数据。
- LongBuffer:用于存储长整型数据。
- FloatBuffer:用于存储浮点型数据。
- DoubleBuffer:用于存储双精度浮点型数据。
11. 什么是直接缓冲区(Direct Buffer)和非直接缓冲区(Non-direct Buffer)?
- 直接缓冲区(Direct Buffer):直接在JVM堆外分配内存空间,通过本地I/O操作直接与操作系统交互,减少了数据在JVM堆与操作系统之间的拷贝,适合高频、大数据量的I/O操作,但创建和销毁成本较高。
- 非直接缓冲区(Non-direct Buffer):在JVM堆中分配内存,数据需要通过JVM堆与操作系统之间的拷贝进行I/O操作,适合小数据量或低频操作,创建和销毁成本低。
12. 直接缓冲区与非直接缓冲区的区别是什么?
- 内存分配位置:直接缓冲区在JVM堆外分配,非直接缓冲区在JVM堆内分配。
- 性能:直接缓冲区减少数据拷贝,适合高频I/O;非直接缓冲区需要数据拷贝,适合低频I/O。
- 生命周期管理:直接缓冲区由JVM通过本地方法管理,非直接缓冲区由JVM垃圾回收器管理。
- 适用场景:直接缓冲区适合大文件或网络传输;非直接缓冲区适合小数据操作。
13. 如何将数据写入Buffer?
通过put()
方法将数据写入Buffer,例如:
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put((byte)1); // 写入一个字节
buffer.put(new byte[]{
1, 2, 3}); // 写入字节数组
14. 如何从Buffer读取数据?
通过get()
方法从Buffer读取数据,例如:
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put((byte)1);
buffer.flip(); // 切换为读模式
byte b = buffer.get(); // 读取一个字节
byte[] dst = new byte[3];
buffer.get(dst); // 读取字节数组
15. 什么是Buffer的翻转(flip)操作?
flip()
方法将Buffer从写模式切换为读模式,具体操作:
- 将
limit
设置为当前position
。 - 将
position
重置为0。
用于准备从Buffer中读取数据。
16. 什么是Buffer的清除(clear)操作?
clear()
方法清空Buffer,准备写入数据,具体操作:
- 将
position
重置为0。 - 将
limit
设置为capacity
。
注意:clear()
不会清空数据,只是重置指针。
17. 什么是Buffer的重绕(rewind)操作?
rewind()
方法将position
重置为0,mark
被丢弃,用于重新读取Buffer中的数据。
18. 什么是Buffer的压缩(compact)操作?
compact()
方法将未读的数据移动到Buffer的开头,并将position
设置为未读数据的末尾,limit
设置为capacity
,用于保留未读数据并准备写入新数据。
19. 什么是Channel的基本概念?
Channel是Java NIO中用于数据传输的抽象,类似于流,但支持双向读写,可以与Buffer配合使用。Channel是双向的,可以从Channel读取数据到Buffer,也可以从Buffer写入数据到Channel。
20. Channel与Stream的区别是什么?
- 方向性:Stream是单向的(输入流或输出流),Channel是双向的。
- 缓冲区:Stream直接操作数据,Channel需要通过Buffer操作数据。
- 阻塞模式:Stream默认是阻塞的,Channel支持非阻塞模式。
21. Channel有哪些类型?
常见的Channel类型包括:
- FileChannel:用于文件I/O。
- SocketChannel:用于TCP网络通信。
- ServerSocketChannel:用于监听TCP连接。
- DatagramChannel:用于UDP网络通信。
22. 如何创建一个FileChannel?
通过FileInputStream
、FileOutputStream
或RandomAccessFile
获取FileChannel:
FileChannel channel = new FileInputStream("file.txt").getChannel();
23. 如何使用FileChannel读取文件?
FileChannel channel = new FileInputStream("file.txt").getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer); // 读取数据到Buffer
buffer.flip(); // 切换为读模式
// 处理Buffer中的数据
channel.close();
24. 如何使用FileChannel写入文件?
FileChannel channel = new FileOutputStream("file.txt").getChannel();
ByteBuffer buffer = ByteBuffer.wrap("Hello".getBytes