面试题答案
一键面试合理选择装饰者类
- 根据功能需求选择:
- 明确业务需求,例如如果需要高效读取二进制数据,优先选择
BufferedInputStream
来装饰InputStream
,以减少磁盘I/O次数。若处理字符数据,BufferedReader
是更好的选择,其针对字符读取做了优化。 - 若要对数据进行加密解密处理,可选择如
CipherInputStream
和CipherOutputStream
来装饰字节流,以满足安全需求。
- 明确业务需求,例如如果需要高效读取二进制数据,优先选择
- 避免过度装饰:过多的装饰者类嵌套会增加复杂性和性能开销。只添加必要的装饰者,例如在简单文本读取场景下,若不需要缓冲之外的特殊功能,仅使用
BufferedReader
装饰FileReader
即可,避免额外添加不必要的装饰者。
处理流的嵌套
- 遵循逻辑顺序:按照数据处理的逻辑顺序进行嵌套。一般来说,字节流在底层,字符流基于字节流构建。例如,若要从文件读取字符数据,应先使用
FileInputStream
作为底层字节流,再用InputStreamReader
将字节流转换为字符流,最后可以用BufferedReader
进行缓冲处理,即BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("file.txt")));
。 - 控制嵌套深度:尽量减少装饰者的嵌套层数,每增加一层嵌套就会增加一定的性能开销和维护成本。例如,对于普通文件读取,通常一到两层装饰(如
BufferedReader
装饰FileReader
)就能满足大部分性能需求,避免无意义的多层嵌套。
有效的资源释放
- 使用
try - with - resources
语句:Java 7引入的try - with - resources
语句可以自动关闭实现了AutoCloseable
接口的资源。例如:
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
在try
块结束时,无论是否发生异常,br
都会自动关闭,确保资源及时释放。
2. 手动关闭外层流:若不使用try - with - resources
,要在finally
块中手动关闭流。并且关闭流时要从外层向内层关闭,例如:
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("file.txt"));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
关闭外层流通常会级联关闭内层流,但对于一些特殊情况(如自定义装饰者未正确实现关闭逻辑),可能需要按顺序手动关闭所有流以确保资源完全释放。