Tổng quan về Xử lý Ngoại lệ, Các lớp Dữ liệu Cơ bản và Collection Framework trong Java

1. Xử lý ngoại lệ (Exception Handling)

Trong lập trình Java, cơ chế xử lý ngoại lệ đóng vai trò quan trọng trong việc duy trì sự ổn định của ứng dụng, ngăn chặn việc chương trình bị dừng đột ngột khi gặp lỗi. Cấu trúc thường dùng bao gồm khối try, catchfinally.

Cấu trúc Try-Catch-Finally

public void divideNumbers() {
    try {
        int numerator = 100;
        int denominator = 0;
        int result = numerator / denominator; 
        System.out.println("Kết quả: " + result);
    } catch (ArithmeticException ex) {
        System.err.println("Phát hiện lỗi chia cho 0: " + ex.getMessage());
    } finally {
        System.out.println("Khối lệnh finally luôn được thực thi để dọn dẹp tài nguyên.");
    }
}

Nguyên tắc khớp ngoại lệ:

  • Khối catch sẽ bắt được ngoại lệ của loại được khai báo cũng như mọi lớp con của nó.
  • Các khối catch phải được sắp xếp từ cụ thể đến chung. Lớp ngoại lệ cha (như Exception) phải đặt sau các lớp con, nếu không trình biên dịch sẽ báo lỗi.
  • Nếu các lớp ngoại lệ không có quan hệ kế thừa, thứ tự xuất hiện không quan trọng.
  • Khối finally là tùy chọn nhưng nếu có, nó sẽ luôn chạy bất kể có ngoại lệ hay không.

Ném ngoại lệ (Throwing Exceptions)

Chúng ta có thể chủ động ném ngoại lệ bằng từ khóa throw hoặc khai báo phương thức ném ngoại lệ bằng throws.

public void validateAge(int age) {
    if (age < 0) {
        throw new IllegalArgumentException("Tuổi không được là số âm");
    }
    System.out.println("Tuổi hợp lệ: " + age);
}

// Sử dụng throws để chuyển trách nhiệm xử lý cho phương thức gọi
public void readFile(String path) throws IOException {
    // Logic đọc file có thể ném IOException
}

Tạo lớp ngoại lệ tùy chỉnh

Để xử lý các lỗi nghiệp vụ cụ thể, chúng ta có thể định nghĩa lớp ngoại lệ mới kế thừa từ Exception hoặc RuntimeException.

public class BusinessRuleException extends Exception {
    private String errorCode;

    public BusinessRuleException(String code, String message) {
        super(message);
        this.errorCode = code;
    }

    @Override
    public String toString() {
        return "Lỗi " + errorCode + ": " + getMessage();
    }
}

2. Các lớp dữ liệu phổ biến (Common Classes)

Lớp bao bọc (Wrapper Classes)

Java là ngôn ngữ hướng đối tượng, nhưng các kiểu dữ liệu nguyên thủy (int, double, v.v.) không phải là đối tượng. Các lớp bao bọc (như Integer, Double) giúp chuyển đổi chúng thành đối tượng để sử dụng trong các cấu trúc dữ liệu như Collection.

// Chuyển đổi từ nguyên thủy sang đối tượng (Boxing)
int value = 50;
Integer wrapperValue = Integer.valueOf(value);

// Chuyển đổi từ đối tượng về nguyên thủy (Unboxing)
int primitiveValue = wrapperValue.intValue();

// Tự động đóng gói và mở gói (Autoboxing/Unboxing)
Integer autoBox = 100; // Tự động chuyển thành Integer
int autoUnbox = autoBox; // Tự động chuyển thành int

Lớp String

String đại diện cho chuỗi ký tự và có tính bất biến (immutable). Một khi đối tượng String được tạo, nội dung của nó không thể thay đổi. Mọi thao tác chỉnh sửa đều tạo ra đối tượng mới.

String greeting = "Xin chào";
String target = new String("Java");
// Nối chuỗi (tạo đối tượng mới)
String message = greeting + " " + target;

// So sánh nội dung chuỗi
boolean isMatch = greeting.equals("Xin chào"); 

Lớp BigDecimal

Trong các tính toán tài chính đòi hỏi độ chính xác cao, floatdouble có thể gây ra lỗi làm tròn. BigDecimal là giải pháp thay thế an toàn hơn cho số thập phân.

import java.math.BigDecimal;

BigDecimal price = new BigDecimal("19.99");
BigDecimal tax = new BigDecimal("0.05");

// Các phép tính toán học
BigDecimal totalTax = price.multiply(tax);
BigDecimal finalPrice = price.add(totalTax);

3. Bộ sưu tập và Generics (Collections and Generics)

Giao diện List

List là một tập hợp có thứ tự, cho phép chứa các phần tử trùng lặp. ArrayList là implementation phổ biến nhất nhờ hiệu suất truy cập ngẫu nhiên tốt.

import java.util.ArrayList;
import java.util.List;

public void listExample() {
    List<String> inventory = new ArrayList<>();
    inventory.add("Laptop");
    inventory.add("Mouse");
    inventory.add("Monitor");

    // Duyệt qua danh sách
    for (String item : inventory) {
        System.out.println("Sản phẩm: " + item);
    }
}

Giao diện Set

Set là tập hợp không cho phép chứa các phần tử trùng lặp. Nó thường được sử dụng để lọc bỏ các dữ liệu thừa. HashSet sử dụng bảng băm để lưu trữ.

import java.util.HashSet;
import java.util.Set;

public void setExample() {
    Set<String> uniqueIds = new HashSet<>();
    uniqueIds.add("ID001");
    uniqueIds.add("ID002");
    uniqueIds.add("ID001"); // Phần tử này sẽ bị bỏ qua vì đã tồn tại

    System.out.println("Số lượng ID duy nhất: " + uniqueIds.size());
}

Giao diện Map

Map lưu trữ dữ liệu dưới dạng cặp khóa-giá trị (Key-Value). Mỗi khóa là duy nhất và dùng để truy xuất giá trị tương ứng. HashMap là lớp triển khai thường gặp nhất.

import java.util.HashMap;
import java.util.Map;

class Product {
    private String code;
    private String label;
    
    public Product(String code, String label) {
        this.code = code;
        this.label = label;
    }
    
    public String getLabel() { return label; }
}

public void mapExample() {
    Map<String, Product> productCatalog = new HashMap<>();
    
    Product p1 = new Product("P101", "Điện thoại");
    Product p2 = new Product("P102", "Tai nghe");
    
    productCatalog.put(p1.code, p1);
    productCatalog.put(p2.code, p2);
    
    // Truy xuất sản phẩm bằng mã
    Product found = productCatalog.get("P101");
    if (found != null) {
        System.out.println("Tìm thấy: " + found.getLabel());
    }
}

Thẻ: Java Exception Handling Collections Framework Generics BigDecimal

Đăng vào ngày 15 tháng 7 lúc 22:49