Java 8 – Annotation – Phần 2


Được đăng vào ngày 11/07/2017 | 0 bình luận
Đánh giá bài viết

Các annotation có sẵn trong Java

Java có sẵn một số annotation được định nghĩa sẵn, thông thường được dùng cho trình biên dịch hoặc dùng cho các annotation khác.

Có 3 annotation được định nghĩa sẵn trong gói java.lang@Deprecated, @Override@SuppressWarnings.

@Deprecated cho biết một phần tử nào đó không còn được sử dụng nữa. Trình biên dịch sẽ in các câu cảnh báo khi chương trình sử dụng các thuộc tính, lớp hoặc phương thức có gắn với @Deprecated.

public class MyClass {
    @Deprecated
    static void deprecated-method() {
        // ...
    }
}

@Override cho biết phần tử đó ghi đè lên một phần tử khác đã được định nghĩa trong lớp cha. Chúng ta sẽ làm việc với các phương thức ghi đè khá nhiều.

public class MyClass extends MySuperClass {
    @Override
    public int override-method() {
        // ...
    }
}

Chúng ta không nhất thiết phải sử dụng @Override khi ghi đè phương thức, nhưng annotation này sẽ giúp chúng ta tránh lỗi dễ dàng hơn.

@SupressWarnings thông báo cho trình biên dịch biết là không được in các câu cảnh báo nào đó. Chẳng hạn như chặn câu cảnh báo deprecated ở trên.

public class MyClass {
    @Deprecated
    static void deprecated-method() {
        //  ...
    }

    @SupressWarnings("deprecation")
    public void supress-method() {
        this.deprecated-method();
    }
}

Tất cả các loại câu cảnh báo trong Java đều thuộc về một trong 2 loại là deprecation hoặc unchecked. Chúng ta có thể loại bỏ cả 2 loại cảnh báo bằng cách truyền vào @SupressWarnings như sau:

@SuppressWarnings({"unchecked", "deprecation"})

Ngoài ra còn có 2 annotation là @SafeVarargs và @FunctionalInterface. 

@SafeVarargs được đặt trước phương thức. có tác dụng kiểm tra xem đoạn code phía sau nó có tạo ra bất cứ một hành động nguy hiểm nào đó hay không, chẳng hạn như kiểm tra xem biến sắp được sử dụng có thể giải phóng lỗi exeption hay không… khi dùng @SafeVarargs thì các câu cảnh báo không được hiện ra.

@FunctionalInterface là annotation có trong Java 8, được đặt trước các giao diện hàm và thông báo cho trình biên dịch biết sau đó là phần khai báo một giao diện của một hàm, chúng ta sẽ tìm hiểu sau.

Lớp annotation

Như đã giới thiệu trong phần trước, đối với phiên bản Java 8 thì các annotation còn có thể được dùng giống như một lớp, tức là có thể dùng trong việc tạo đối tượng, ép kiểu, kế thừa…v.v

Lớp annotation được sử dụng với mục đích hỗ trợ cho việc phân tích chương trình, nhằm tăng tính type-checking, tức là đảm bảo cho biến hoặc đối tượng luôn lưu trữ một dữ liệu trong một ngữ cảnh nào đó. Chẳng hạn như chúng ta có thể quy định một biến không bao giờ được gán giá trị null, nhờ đó mà không bao giờ xảy ra lỗi NullPointerException, bằng cách sử dụng một annotation nào đó mà chúng ta tự định nghĩa, chẳng hạn như:

@NonNull String str;

Khi chúng ta biên dịch thì trình biên dịch sẽ in những câu thông báo lỗi nếu các biến có thể gây ra một lỗi nào đó, nhờ đó mà chúng ta sửa lại kịp thời trước khi chạy.

Đây là một tính năng khá mới, bạn có thể tìm hiểu thêm trên mạng, ở đây chúng ta không đi sâu.

Khai báo nhiều annotation trùng tên

Sẽ có trường hợp chúng ta muốn sử dụng một annotation nhiều lần tại một vị trí, Java 8 hỗ trợ tính năng này.

Ví dụ như chúng ta muốn viết một chương trình tự động thực hiện một công việc nào đó tại một thời điểm nào đó tương tự như dịch vụ cron. Giả sử chúng ta muốn đặt thời gian thực hiện một việc vào cuối tuần, rồi lại muốn đặt thời gian thực hiện một việc khác vào đầu tuần, chúng ta có thể định định nghĩa và khai báo 2 annotation dạng như sau:

@Schedule(date="Mon")
@Schedule(date="Sun")
public void someCron() {
    // ...
}

Để có thể sử dụng một annotation nhiều lần thì chúng ta phải khai báo một annotation khác dùng để chứa annotation lặp theo 2 bước dưới đây.

Bước 1: Khai báo kiểu annotation có thể lặp

Để khai báo một annotation có thể lặp thì chúng ta khai báo một annotation khác cho nó là @Repeatable. Ví dụ:

import java.lang.annotation.Repeatable;

@Repeatable(Schedules.class)
public @interface Schedule {
     String date() default "Mon";
}

Bên trong @Repeatable chúng ta phải truyền vào class của một annotation khác dùng để chứa @Schedule, ở đây là Schedules.class (lưu ý khác với Schedule). Tức là @Schedules sẽ chứa các @Schedule.

Bước 2: Khai báo annotation dùng để chứa

Kiểu annotation dùng để chứa annotation khác phải có một thuộc tính có tên là value. Kiểu dữ liệu được chứa phải là kiểu mảng. Ví dụ:

 

public @interface Schedules {
    Schedule[] value();
}

Được đăng vào ngày 11/07/2017