try-with-resources形式是 try (Resource r = ...) { ... },編譯器會自動在區塊結束時呼叫 r.close()。
任何實作了 java.lang.AutoCloseable(或 java.io.Closeable) 的物件都可以放進 try-with-resources。
Socket 實作了 Closeable,所以可以放進去。
即使區塊內拋出例外,資源也會被自動關閉。若 close() 本身又拋例外,該例外會被標記為 suppressed exception(被附加到最初拋出的例外上,不會蓋掉原始例外)。
優點:程式更安全、較少資源外洩(resource leak),程式碼也更乾淨。。
「AutoCloseable」 是一個 介面(interface),定義了物件可以被自動關閉的方法。
它只有一個抽象方法:
public interface AutoCloseable {
void close() throws Exception;
}
實作這個介面的物件,可以放在 try-with-resources 裡面。
try-with-resources 會在區塊結束時自動呼叫 close(),即使程式中間拋例外,也保證資源被釋放。
所有 Closeable(例如 FileInputStream、BufferedReader)都實作了 AutoCloseable。
package day1;
import java.io.IOException;
import java.net.*;
public class Day10Demo {
public enum PortStatus {
OPEN,
CLOSED,
TIMEOUT,
UNKNOWN_HOST,
ERROR
}
public static PortStatus checkPort(String host, int port, int timeoutMs) {
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(host, port), timeoutMs);
// 若 connect 成功,會執行到這裡;try 區塊結束時 socket.close() 會自動被呼叫
return PortStatus.OPEN;
} catch (ConnectException e) {
return PortStatus.CLOSED;
} catch (SocketTimeoutException e) {
return PortStatus.TIMEOUT;
} catch (UnknownHostException e) {
return PortStatus.UNKNOWN_HOST;
} catch (IOException e) {
return PortStatus.ERROR;
}
}
public static void main(String[] args) {
String host = "localhost";
int[] ports = {22, 80, 8080, 9999};
int timeoutMs = 2000;
for (int port : ports) {
PortStatus status = checkPort(host, port, timeoutMs);
System.out.println("port:" + port + " 狀態:" + status);
}
}
}
AutoCloseable:任何實作它的物件都能用在 try-with-resources,確保自動關閉。
try-with-resources:語法簡潔、避免資源外洩,也會處理 close() 拋例外的情況。
Java 7 之後建議所有 I/O 或需要釋放資源的物件都用 try-with-resources。
這段程式碼在day9做修改,今天使用 try-with-resources 自動關閉 Socket,
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(host, port), timeoutMs);
今天學到了 try-with-resources 這樣不需要手動寫 socket.close(),讓程式更乾淨,且無論 try 區塊中是否拋出例外,Socket 都會自動關閉,更安全,不會有資源洩漏的風險。