Java 7起Socket实现AutoCloseable可直接try-with-resources自动关闭;更推荐将BufferedReader/Writer等高层流纳入资源管理,确保级联关闭;连接超时等异常需手动close防泄露。

Java 中可以用 try-with-resources 自动关闭 Socket,但要注意:Socket 本身实现了 AutoCloseable,所以能直接用;不过实际使用中更推荐包装成更高层的资源(比如 BufferedReader / BufferedWriter),让所有关联流一并释放。
Socket 本身支持 try-with-resources
从 Java 7 开始,Socket 类实现了 AutoCloseable 接口,因此可以直接在 try-with-resources 中声明:
try (Socket socket = new Socket("example.com", 80)) {
// 使用 socket 发送/接收数据
OutputStream out = socket.getOutputStream();
out.write("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n".getBytes());
InputStream in = socket.getInputStream();
// 读取响应...
} catch (IOException e) {
e.printStackTrace();
}
这样写会在 try 块结束时自动调用 socket.close(),无需手动写 finally。
更安全的做法:把输入输出流也纳入资源管理
仅靠关闭 Socket 不一定立即释放底层流(尤其在异常提前发生时)。为确保 InputStream 和 OutputStream 也被及时关闭,应将它们也声明为 try-with-resources 的资源:
- 注意:
Socket.getInputStream()和getOutputStream()返回的流本身也实现了AutoCloseable(自 Java 7 起) - 但它们的
close()方法会委托给 Socket 的close(),所以多个 close 不会报错,但顺序很重要 - 建议按“先打开、后关闭”的反序声明资源(即 Socket 最后声明),避免流在 Socket 关闭后还被操作
try (
Socket socket = new Socket("example.com", 80);
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream()
) {
out.write("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n".getBytes());
// 读取响应...
} catch (IOException e) {
e.printStackTrace();
}
配合字符流时,优先封装 BufferedReader/Writer
如果需要按行读写文本(如 HTTP、自定义协议),建议用 BufferedReader 和 BufferedWriter 包装,并把它们作为资源管理对象:
- 它们内部持有了底层流的引用,
close()会级联关闭底层流和 Socket - 记得指定字符集(如
StandardCharsets.UTF_8),避免平台默认编码问题 - 不要单独关闭底层流——否则上层流再 close 会抛
IOException
try (
Socket socket = new Socket("example.com", 80);
OutputStream out = socket.getOutputStream();
Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
BufferedWriter bufferedWriter = new BufferedWriter(writer);
InputStream in = socket.getInputStream();
Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
BufferedReader bufferedReader = new BufferedReader(reader)
) {
bufferedWriter.write("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n");
bufferedWriter.flush();
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
注意连接未建立成功时的资源状态
如果 new Socket(host, port) 抛出异常(如 UnknownHostException 或 ConnectException),则 try-with-resources 不会执行任何 close() ——这是正常的,因为对象根本没创建成功。但若使用带超时的构造(如 new Socket().connect(..., timeout)),需自己处理部分初始化失败的情况:
- 先创建 Socket 实例,再 connect,失败时主动 close 防止句柄泄露
- 此时 try-with-resources 不适用,改用传统 try-catch-finally
Socket socket = null;
try {
socket = new Socket();
socket.connect(new InetSocketAddress("example.com", 80), 5000);
// 后续使用...
} catch (IOException e) {
throw e;
} finally {
if (socket != null && !socket.isClosed()) {
try {
socket.close();
} catch (IOException ignored) {}
}
}
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











