Try-Catch trong Java 🛡️
🎯 Mục tiêu: Học cách sử dụng try-catch để xử lý các ngoại lệ trong Java một cách an toàn và hiệu quả.
Giới thiệu 📝
Try-catch là cơ chế xử lý ngoại lệ (exception handling) cơ bản trong Java. Nó cho phép chúng ta bắt và xử lý các ngoại lệ có thể xảy ra trong quá trình thực thi chương trình, giúp chương trình không bị dừng đột ngột và có thể phục hồi từ các lỗi.
💡 Fun Fact: Try-catch được thiết kế để giúp chương trình của bạn "fail gracefully" (thất bại một cách duyên dáng) thay vì crash đột ngột.
1. Cú Pháp Cơ Bản ⚡
Try-Catch Đơn Giản
try {
// Code có thể gây ra ngoại lệ
int result = 10 / 0; // ArithmeticException
} catch (ArithmeticException e) {
// Xử lý ngoại lệ
System.out.println("Lỗi chia cho 0: " + e.getMessage());
}
Try-Catch với Nhiều Catch
try {
// Code có thể gây ra nhiều loại ngoại lệ
int[] arr = new int[5];
arr[10] = 1; // ArrayIndexOutOfBoundsException
String str = null;
str.length(); // NullPointerException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Lỗi truy cập mảng: " + e.getMessage());
} catch (NullPointerException e) {
System.out.println("Lỗi null pointer: " + e.getMessage());
}
Try-Catch với Finally
try {
// Code có thể gây ra ngoại lệ
FileReader reader = new FileReader("file.txt");
} catch (FileNotFoundException e) {
System.out.println("Không tìm thấy file: " + e.getMessage());
} finally {
// Code luôn được thực thi
System.out.println("Kết thúc xử lý");
}
2. Try-With-Resources 🔄
Cú Pháp Cơ Bản
try (FileReader reader = new FileReader("file.txt")) {
// Sử dụng reader
} catch (IOException e) {
System.out.println("Lỗi đọc file: " + e.getMessage());
}
Nhiều Resources
try (FileReader reader = new FileReader("input.txt");
FileWriter writer = new FileWriter("output.txt")) {
// Sử dụng reader và writer
} catch (IOException e) {
System.out.println("Lỗi xử lý file: " + e.getMessage());
}
3. Xử Lý Ngoại Lệ Phân Cấp 🎯
Catch Ngoại Lệ Cụ Thể
try {
// Code có thể gây ra ngoại lệ
int result = Integer.parseInt("abc"); // NumberFormatException
} catch (NumberFormatException e) {
System.out.println("Lỗi định dạng số: " + e.getMessage());
} catch (Exception e) {
System.out.println("Lỗi khác: " + e.getMessage());
}
Catch Ngoại Lệ Cha
try {
// Code có thể gây ra ngoại lệ
FileReader reader = new FileReader("file.txt");
} catch (IOException e) {
// Bắt cả FileNotFoundException và các ngoại lệ IO khác
System.out.println("Lỗi IO: " + e.getMessage());
}
4. Ví Dụ Thực Tế 🚀
Xử Lý File
public class FileHandler {
public String readFile(String path) {
try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
StringBuilder content = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
content.append(line).append("\n");
}
return content.toString();
} catch (FileNotFoundException e) {
System.out.println("Không tìm thấy file: " + e.getMessage());
return null;
} catch (IOException e) {
System.out.println("Lỗi đọc file: " + e.getMessage());
return null;
}
}
}
Xử Lý Kết Nối Database
public class DatabaseHandler {
public void connect() {
Connection conn = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db");
System.out.println("Kết nối thành công");
} catch (SQLException e) {
System.out.println("Lỗi kết nối database: " + e.getMessage());
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
System.out.println("Lỗi đóng kết nối: " + e.getMessage());
}
}
}
}
}
Xử Lý API Request
public class ApiHandler {
public String makeRequest(String url) {
try (HttpClient client = HttpClient.newHttpClient()) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.GET()
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
return response.body();
} catch (IOException e) {
System.out.println("Lỗi kết nối: " + e.getMessage());
return null;
} catch (InterruptedException e) {
System.out.println("Request bị gián đoạn: " + e.getMessage());
return null;
}
}
}
5. Best Practices ✅
-
Catch Ngoại Lệ Cụ Thể
// Không nên
try {
// Code
} catch (Exception e) {
// Xử lý chung
}
// Nên
try {
// Code
} catch (FileNotFoundException e) {
// Xử lý file không tồn tại
} catch (IOException e) {
// Xử lý lỗi IO
} -
Sử Dụng Try-With-Resources
// Không nên
FileReader reader = null;
try {
reader = new FileReader("file.txt");
} finally {
if (reader != null) {
reader.close();
}
}
// Nên
try (FileReader reader = new FileReader("file.txt")) {
// Sử dụng reader
} -
Xử Lý Ngoại Lệ Phù Hợp
// Không nên
catch (Exception e) {
e.printStackTrace();
}
// Nên
catch (Exception e) {
logger.error("Lỗi xử lý: " + e.getMessage());
// Thực hiện các hành động phục hồi nếu cần
}
6. Lỗi Thường Gặp ⚠️
-
Quên Đóng Resource
// Lỗi
FileReader reader = new FileReader("file.txt");
// Quên đóng reader
// Đúng
try (FileReader reader = new FileReader("file.txt")) {
// Sử dụng reader
} -
Catch Ngoại Lệ Sai Thứ Tự
// Lỗi
try {
// Code
} catch (Exception e) {
// Xử lý chung
} catch (IOException e) {
// Không bao giờ được thực thi
}
// Đúng
try {
// Code
} catch (IOException e) {
// Xử lý IO
} catch (Exception e) {
// Xử lý chung
} -
Quên Xử Lý Ngoại Lệ
// Lỗi
public void processFile() {
FileReader reader = new FileReader("file.txt");
// Quên try-catch
}
// Đúng
public void processFile() {
try (FileReader reader = new FileReader("file.txt")) {
// Xử lý file
} catch (IOException e) {
logger.error("Lỗi xử lý file: " + e.getMessage());
}
}
7. Ví Dụ Thực Tế Nâng Cao 🎯
Xử Lý Đa Luồng
public class ThreadHandler {
public void processWithRetry(Runnable task, int maxRetries) {
int retries = 0;
while (retries < maxRetries) {
try {
task.run();
return;
} catch (Exception e) {
retries++;
if (retries == maxRetries) {
System.out.println("Đã thử lại " + maxRetries + " lần nhưng vẫn thất bại");
throw e;
}
System.out.println("Lỗi xảy ra, thử lại lần " + retries);
try {
Thread.sleep(1000); // Đợi 1 giây trước khi thử lại
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
}
}
Xử Lý Giao Dịch
public class TransactionHandler {
public void processTransaction(Connection conn, double amount) {
try {
conn.setAutoCommit(false);
// Thực hiện các thao tác
updateBalance(conn, "sender", -amount);
updateBalance(conn, "receiver", amount);
conn.commit();
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException ex) {
System.out.println("Lỗi rollback: " + ex.getMessage());
}
System.out.println("Lỗi giao dịch: " + e.getMessage());
} finally {
try {
conn.setAutoCommit(true);
} catch (SQLException e) {
System.out.println("Lỗi reset auto commit: " + e.getMessage());
}
}
}
}
Xử Lý Cache
public class CacheHandler {
private Map<String, String> cache = new HashMap<>();
public String getValue(String key) {
try {
return cache.get(key);
} catch (Exception e) {
System.out.println("Lỗi truy cập cache: " + e.getMessage());
return null;
}
}
public void setValue(String key, String value) {
try {
cache.put(key, value);
} catch (Exception e) {
System.out.println("Lỗi cập nhật cache: " + e.getMessage());
}
}
}
💡 Lời khuyên: Hãy thực hành với các ví dụ thực tế để hiểu rõ hơn về cách sử dụng try-catch trong các tình huống khác nhau.
Tiếp Theo 🎯
Trong các bài học tiếp theo, chúng ta sẽ:
- Tìm hiểu về throw và throws
- Học cách tạo custom exceptions
- Thực hành với các ví dụ thực tế
- Tìm hiểu về exception chaining