0
0
Lập trình
TT

Tổng Quan Về Pattern Matching Trong Java Hiện Đại

Đăng vào 6 ngày trước

• 5 phút đọc

1. Giới thiệu

Pattern Matching trong Java là khả năng kiểm tra một đối tượng với một mẫu và trích xuất dữ liệu từ nó một cách an toàn và ngắn gọn. Thay vì sử dụng kiểm tra instanceof kèm theo ép kiểu, pattern matching cho phép bạn kết hợp các thao tác này lại với nhau.

2. Pattern Matching cho instanceof

Trước Java 16:

java Copy
if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.toUpperCase());
}

Với Pattern Matching:

java Copy
if (obj instanceof String s) {
    System.out.println(s.toUpperCase());
}

Điểm nổi bật:

  • Loại bỏ việc ép kiểu không cần thiết.
  • Biến s chỉ có sẵn trong khối if.
  • Hoạt động với phạm vi luồng: nếu trình biên dịch biết obj là một String, bạn có thể sử dụng nó.

3. Pattern Matching cho switch

switch truyền thống:

java Copy
static String format(Object obj) {
    return switch (obj) {
        case Integer i -> "int " + i;
        case Long l    -> "long " + l;
        case String s  -> "String " + s.toUpperCase();
        default        -> obj.toString();
    };
}

Tính năng:

  • Không cần ép kiểu rõ ràng.
  • Hỗ trợ các lớp sealed (xem phần tiếp theo).
  • Có thể khớp với null an toàn bằng case null.

4. Record Patterns

Records rất hữu ích cho việc lưu trữ dữ liệu. Record patterns cho phép bạn phân tách chúng bên trong switch hoặc if.

java Copy
record Point(int x, int y) {}

static String printPoint(Object obj) {
    return switch (obj) {
        case Point(int x, int y) -> "Point tại (" + x + ", " + y + ")";
        default -> "Không phải là một điểm";
    };
}

Record patterns lồng nhau:

java Copy
record Rectangle(Point topLeft, Point bottomRight) {}

static void printRectangle(Rectangle r) {
    if (r instanceof Rectangle(Point(int x1, int y1), Point(int x2, int y2))) {
        System.out.println("Hình chữ nhật từ (" + x1 + "," + y1 + ") đến (" + x2 + "," + y2 + ")");
    }
}

5. Sealed Types với Pattern Matching

Các lớp sealed cho phép bạn kiểm soát việc kế thừa. Pattern matching hoạt động hoàn hảo với chúng.

java Copy
sealed interface Shape permits Circle, Rectangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}

static double area(Shape shape) {
    return switch (shape) {
        case Circle c -> Math.PI * c.radius() * c.radius();
        case Rectangle r -> r.width() * r.height();
    };
}

Shape là sealed, trình biên dịch kiểm tra tính đầy đủ — không cần default.

6. Guarded Patterns

Đôi khi bạn cần một điều kiện bổ sung cho một trường hợp.

java Copy
static String typeOfNumber(Number n) {
    return switch (n) {
        case Integer i when i > 0 -> "số nguyên dương";
        case Integer i -> "số nguyên không dương";
        case Long l when l > 0 -> "số nguyên dài dương";
        default -> "số khác";
    };
}

7. Record Patterns trong vòng lặp for

Bạn có thể phân tách các record trực tiếp trong vòng lặp.

java Copy
record Point(int x, int y) {}

List<Point> points = List.of(new Point(1, 2), new Point(3, 4));

for (Point(int x, int y) : points) {
    System.out.println("x=" + x + ", y=" + y);
}

8. Primitive Patterns

Pattern matching được mở rộng đến các kiểu nguyên thủy. Điều này cho phép xử lý số một cách ngắn gọn hơn.

java Copy
static String describe(Object obj) {
    return switch (obj) {
        case int i -> "int: " + i;
        case long l -> "long: " + l;
        case double d -> "double: " + d;
        case null -> "giá trị null";
        default -> "không xác định";
    };
}

Lợi ích của việc sử dụng Primitive Patterns:

  • Loại bỏ overhead của boxing/unboxing và biến pattern matching trở nên phổ quát.

9. Các Thực Hành Tốt Nhất

  • Luôn sử dụng pattern matching khi có thể để cải thiện tính rõ ràng của mã.
  • Kiểm tra các trường hợp biên để đảm bảo mã của bạn an toàn trước các loại dữ liệu không mong muốn.

10. Những Cạm Bẫy Thường Gặp

  • Không sử dụng pattern matching với các kiểu dữ liệu không rõ ràng có thể dẫn đến lỗi.
  • Bỏ qua kiểm tra null có thể gây ra NullPointerException.

11. Mẹo Tối Ưu Hiệu Suất

  • Sử dụng pattern matching thay cho các cấu trúc điều kiện phức tạp để cải thiện hiệu suất và khả năng đọc mã.
  • Giảm thiểu số lần ép kiểu không cần thiết có thể làm giảm hiệu suất.

FAQ

Q: Pattern matching có hỗ trợ cho tất cả các kiểu dữ liệu không?
A: Không, pattern matching chủ yếu hỗ trợ cho các kiểu dữ liệu đã được định nghĩa rõ ràng như record, sealed, và các kiểu nguyên thủy.
Q: Có thể kết hợp pattern matching với các thư viện khác không?
A: Có, bạn có thể sử dụng pattern matching trong các thư viện Java thông thường mà bạn đang sử dụng.

Kết luận

Pattern matching trong Java mang lại nhiều lợi ích cho lập trình viên, giúp mã nguồn trở nên rõ ràng và dễ bảo trì hơn. Hãy thử áp dụng pattern matching trong dự án của bạn để trải nghiệm những lợi ích mà nó mang lại!

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào