AutoCloseable 接口
概述
AutoCloseable 是从 jdk7 开始存在的接口,位于 java.lang 包中,用于自动执行资源关闭操作。AutoCloseable 接口定义了一个名为 close() 的方法,用于关闭资源。通常在实现 AutoCloseable 接口的类中重写 close() 方法来实现自定义关闭资源的逻辑,例如关闭文件、释放网络连接等。
AutoCloseable 接口是为了配合 Java 7 引入的 try-with-resources(try-catch-finally) 语句而设计的。使用 try-with-resources 语句可以自动关闭实现了 AutoCloseable 接口的资源,无需显式调用 close() 方法,确保资源在使用完毕后被正确关闭,提高代码的可靠性和安全性。
示例
1、在 try-catch-finally 中使用 AutoCloseable 来自动关闭资源:
自定义类实现 AutoCloseable 并重写 close() 方法:
public class StreamExample implements AutoCloseable {
private BufferedReader reader;
public StreamExample(String filePath) throws IOException {
reader = new BufferedReader(new FileReader(filePath));
}
public String readLine() throws IOException {
return reader.readLine();
}
/**
* 重写 close() 方法,自定义关闭资源逻辑
* @throws IOException
*/
@Override
public void close() throws IOException {
reader.close();
}
}
在 try-catch-finally 中的使用:
public class BaseTest {
public static void main(String[] args) {
// 在 try() 中使用自定义对象,在执行完 try 逻辑后会自动调用 close() 方法关闭资源。
// 这样无需在 catch 或 finally 中编写关闭资源的逻辑了。
try (StreamExample example = new StreamExample("file.txt")) {
String line = example.readLine();
while (line != null) {
System.out.println(line);
line = example.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2、不一定用来关闭资源,可以扩展为其它使用场景:
比如在 for 循环语句中,遍历每一个元素时,为每一个元素处理日志设置不同的 traceId,方便日志定位跟踪。
@Slf4j
public class TraceExample implements AutoCloseable {
/**
* 进入循环之前的traceId
*/
private String beforeTraceId;
public TraceExample(String beforeTraceId) {
try {
this.beforeTraceId = beforeTraceId;
// 处理不同集合元素使用不同的 traceId,方便定位日志
String newTraceId = UUID.randomUUID().toString().replaceAll("-", "");
MDC.put("traceId", newTraceId);
} catch (Exception e) {
log.error("TraceExample init error", e);
}
}
@Override
public void close() {
try {
// 集合处理完后恢复遍历集合之前的 traceId
MDC.put("traceId", this.beforeTraceId);
} catch (Exception e) {
log.error("TraceExample init error", e);
}
}
}
结合 try-catch-finally 在循环语句中使用:
public class BaseTest {
public static void main(String[] args) {
List<String> listData = Arrays.asList("1","2", "3");
for (int i = 0; i < listData.size(); i++) {
// 在处理元素之前设置新的 traceId,元素处理完后再恢复原 traceId。
try (TraceExample ignored = new TraceExample("beforeTraceId")) {
System.out.println("处理元素:" + listData.get(i));
System.out.println("每个元素处理过程中,新的traceId:" + MDC.get("traceId"));
} catch (Exception e) {
throw e;
}
System.out.println("原来的 traceId:" + MDC.get("traceId"));
}
}
}