IO流面试题
什么是 Java IO?
Java IO(Input/Output)是 Java 中用于处理输入输出操作的一套 API,它提供了丰富的类和接口,可用于从不同数据源(如文件、网络、内存等)读取数据,以及将数据写入到不同的目标位置。借助 Java IO,开发者能够方便地进行文件读写、网络通信等操作。
如何从数据传输方式理解 IO 流?
从数据传输方式来看,IO 流可分为字节流和字符流。字节流以字节(8 位)为单位进行数据传输,适用于处理二进制数据,像图片、音频、视频等;字符流以字符(16 位)为单位进行数据传输,主要用于处理文本数据,会自动处理字符编码和解码。
Java IO 设计上使用了什么设计模式?
Java IO 设计运用了装饰器模式。装饰器模式允许在不改变原有对象结构的前提下,动态地为对象添加额外的功能。在 Java IO 中,FilterInputStream
和 FilterOutputStream
及其子类就是装饰器类,能够对基本的输入输出流进行包装,从而添加缓冲、加密等额外功能。
怎么理解同步 IO 和异步 IO?
- 同步 IO:在同步 IO 中,当一个线程发起一个 IO 操作后,该线程会一直等待,直到 IO 操作完成才会继续执行后续代码。也就是说,线程在等待 IO 操作结果时会被阻塞,无法进行其他工作。
- 异步 IO:异步 IO 中,线程发起 IO 操作后不会等待操作完成,而是继续执行后续代码。当 IO 操作完成后,系统会通过回调函数、事件通知等方式告知线程操作结果。
怎么理解阻塞 IO 和非阻塞 IO?
- 阻塞 IO:当线程执行 IO 操作时,如果没有数据可读或可写,线程会被阻塞,进入等待状态,直到有数据可用或操作完成。在此期间,线程无法执行其他任务。
- 非阻塞 IO:线程执行 IO 操作时,如果没有数据可读或可写,线程不会被阻塞,而是会立即返回一个结果(如返回 -1 表示没有数据),线程可以继续执行其他任务。
IO 中的输入流和输出流有什么区别?
- 输入流:用于从数据源(如文件、网络等)读取数据到程序中。输入流的主要方法是
read()
,用于读取数据。 - 输出流:用于将程序中的数据写入到目标位置(如文件、网络等)。输出流的主要方法是
write()
,用于写入数据。
字节流和字符流的区别?
- 数据单位:字节流以字节为单位传输数据,字符流以字符为单位传输数据。
- 适用场景:字节流适用于处理二进制数据,字符流适用于处理文本数据。
- 编码处理:字节流不处理字符编码,字符流会自动处理字符编码和解码。
如何将字节流转化为字符流?
可以使用 InputStreamReader
和 OutputStreamWriter
这两个转换流来实现字节流到字符流的转换。例如:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class ByteToCharStream {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("test.txt");
InputStreamReader isr = new InputStreamReader(fis)) {
int data;
while ((data = isr.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
什么是 Java 序列化和反序列化?
- 序列化:将 Java 对象转换为字节序列的过程,以便将对象存储到文件、数据库或通过网络传输。
- 反序列化:将字节序列恢复为 Java 对象的过程,通常在读取存储的对象或接收网络传输的对象时使用。
如何实现 Java 序列化?
要实现 Java 序列化,对象所属的类必须实现 java.io.Serializable
接口,该接口是一个标记接口,没有任何方法。示例如下:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Person implements Serializable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
public class SerializationExample {
public static void main(String[] args) {
Person person = new Person("John", 30);
try (FileOutputStream fos = new FileOutputStream("person.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(person);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Filter 流是什么?
Filter
流是 Java IO 中的装饰器类,用于对基本的输入输出流进行包装,添加额外的功能。它继承自 FilterInputStream
或 FilterOutputStream
,可以在不改变原有流结构的情况下,为流添加缓冲、加密、压缩等功能。
Filter 流有哪些可用?
常见的 Filter
流有:
BufferedInputStream
和BufferedOutputStream
:提供缓冲功能,提高读写效率。DataInputStream
和DataOutputStream
:用于读写基本数据类型。PrintStream
:用于格式化输出。
如何实现对象克隆?
在 Java 中,实现对象克隆有两种方式:
- 浅克隆:实现
Cloneable
接口,并重写clone()
方法。浅克隆只会复制对象的基本数据类型和引用类型的引用,而不会复制引用类型的对象本身。
class MyClass implements Cloneable {
private int value;
public MyClass(int value) {
this.value = value;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public int getValue() {
return value;
}
}
- 深克隆:通过序列化和反序列化实现,能够复制对象及其引用的所有对象。
import java.io.*;
class DeepCopyExample implements Serializable {
private int value;
public DeepCopyExample(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public DeepCopyExample deepCopy() throws IOException, ClassNotFoundException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (DeepCopyExample) ois.readObject();
}
}
Java 中有几种类型的流?
Java 中的流主要分为四大类:
- 字节输入流:
InputStream
及其子类。 - 字节输出流:
OutputStream
及其子类。 - 字符输入流:
Reader
及其子类。 - 字符输出流:
Writer
及其子类。
如何从数据操作上理解 IO 流?
从数据操作角度看,IO 流可分为节点流和处理流。节点流直接与数据源或目标相连,负责实际的数据读写操作,如 FileInputStream
、FileOutputStream
等;处理流是对节点流的包装,用于提供额外的功能,如缓冲、加密等,如 BufferedInputStream
、BufferedOutputStream
等。
BIO、NIO、AIO 三者区别以及适用场景?
- BIO(Blocking IO):
- 特点:同步阻塞 IO,线程在进行 IO 操作时会被阻塞,直到操作完成。
- 适用场景:适用于连接数较少且固定的场景,如传统的 Web 服务器。
- NIO(Non-blocking IO):
- 特点:同步非阻塞 IO,通过
Selector
实现单线程管理多个通道,线程在没有数据可读或可写时不会被阻塞。 - 适用场景:适用于连接数多且连接时间短的场景,如聊天服务器、即时通讯系统等。
- 特点:同步非阻塞 IO,通过
- AIO(Asynchronous IO):
- 特点:异步非阻塞 IO,线程发起 IO 操作后无需等待,操作完成后系统会通知线程。
- 适用场景:适用于连接数多且连接时间长的场景,如文件服务器、数据库服务器等。