Trong hướng dẫn này, chúng ta sẽ tìm hiểu về các loại chú thích Java khác nhau với sự trợ giúp của các ví dụ.

Chú thích Java là siêu dữ liệu (dữ liệu về dữ liệu) cho mã nguồn chương trình của chúng ta. Có một số chú thích được định nghĩa trước được cung cấp bởi Java SE. Hơn nữa, chúng ta cũng có thể tạo các chú thích tùy chỉnh theo nhu cầu của mình.

Nếu bạn không biết chú thích là gì, hãy truy cập hướng dẫn chú thích trong Java ở bài trước.

Các chú thích này có thể được phân loại thành:

1. Chú thích được khai báo sẵn trước trong Java

  • @Deprecated
  • @Override
  • @SuppressWarnings
  • @SafeVarargs
  • @FunctionalInterface

2. Chú thích tùy chỉnh

3. Meta-annotations

  • @Retention
  • @Documented
  • @Target
  • @Inherited
  • @Repeatable

1. Các loại chú thích được khai báo trước

1.1 @Deprecated

 chú thích @Deprecated là một chú thích đánh dấu cho biết các phần tử (lớp, phương thức, thuộc tính, vv) bị phản đối, không dùng nữa và đã được thay thế bởi một yếu tố mới.

Cú pháp của nó là:

@Deprecated
accessModifier returnType deprecatedMethodName() { ... }

Khi một chương trình sử dụng phần tử đã được tuyên bố là không dùng nữa, trình biên dịch sẽ tạo ra một cảnh báo.

Chúng ta sử dụng thẻ @deprecated Javadoc để ghi lại phần tử không dùng nữa.

/**
 * @deprecated
 * why it was deprecated
 */
@Deprecated
accessModifier returnType deprecatedMethodName() { ... }

Ví dụ 1: Ví dụ về chú thích @Deprecated


/*
Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
@author cafedevn
Contact: cafedevn@gmail.com
Fanpage: https://www.facebook.com/cafedevn
Group: https://www.facebook.com/groups/cafedev.vn/
Instagram: https://instagram.com/cafedevn
Twitter: https://twitter.com/CafedeVn
Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
Pinterest: https://www.pinterest.com/cafedevvn/
YouTube: https://www.youtube.com/channel/UCE7zpY_SlHGEgo67pHxqIoA/
*/
class Main {
  /**
   * @deprecated
   * This method is deprecated and has been replaced by newMethod()
   */
  @Deprecated
  public static void deprecatedMethod() { 
    System.out.println("Deprecated method"); 
  } 

  public static void main(String args[]) {
    deprecatedMethod();
  }
}

Đầu ra

Deprecated method

1.2. @Override

@Override quy định cụ thể chú thích rằng một phương thức của một lớp con override phương thức của lớp cha có cùng tên phương thức, kiểu trả về, và danh sách tham số.

Nó không bắt buộc phải sử dụng @Override khi ghi đè một phương thức. Tuy nhiên, nếu chúng ta sử dụng nó, trình biên dịch sẽ báo lỗi nếu có gì đó sai (chẳng hạn như kiểu tham số sai) trong khi ghi đè phương thức.

Ví dụ 2: Ví dụ về chú thích @Override

class Animal {

  // overridden method
  public void display(){
    System.out.println("I am an animal");
  }
}

class Dog extends Animal {

  // overriding method
  @Override
  public void display(){
    System.out.println("I am a dog");
  }

  public void printMessage(){
    display();
  }
}

class Main {
  public static void main(String[] args) {
    Dog dog1 = new Dog();
    dog1.printMessage();
  }
}

Đầu ra

I am a dog

Trong ví dụ này, bằng cách tạo một đối tượng dog1 của lớp Dog, chúng ta có thể gọi phương thức của nó printMessage() mà sau đó thực hiện câu lệnh display().

Vì display() được định nghĩa trong cả hai lớp nên phương thức của lớp Dog con ghi đè phương thức của lớp cha Animal. Do đó, display() của lớp con được gọi.

1.3. @SuppressWarnings

Như tên cho thấy, chú thích @SuppressWarnings hướng dẫn trình biên dịch loại bỏ các cảnh báo được tạo ra trong khi chương trình thực thi.

Chúng ta có thể chỉ định loại cảnh báo sẽ bị loại bỏ. Các cảnh báo có thể bị loại bỏ là dành riêng cho trình biên dịch nhưng có hai loại cảnh báo: không dùng nữakhông được chọn .

Để loại bỏ một danh mục cảnh báo cụ thể, chúng ta sử dụng:

@SuppressWarnings("warningCategory")

Ví dụ,

 @SuppressWarnings("deprecated")

Để loại bỏ nhiều loại cảnh báo, chúng ta sử dụng:

@SuppressWarnings({"warningCategory1", "warningCategory2"})

Ví dụ,

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

Loại deprecated hướng dẫn trình biên dịch loại bỏ cảnh báo khi chúng ta sử dụng phần tử không được dùng nữa.

Loại unchecked hướng dẫn trình biên dịch loại bỏ các cảnh báo khi chúng ta sử dụng các loại cơ bản.

Và, các cảnh báo không định nghĩa được bỏ qua. Ví dụ,

@SuppressWarnings("someundefinedwarning")

Ví dụ 3: Ví dụ về chú thích @SuppressWarnings

/*
Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
@author cafedevn
Contact: cafedevn@gmail.com
Fanpage: https://www.facebook.com/cafedevn
Group: https://www.facebook.com/groups/cafedev.vn/
Instagram: https://instagram.com/cafedevn
Twitter: https://twitter.com/CafedeVn
Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
Pinterest: https://www.pinterest.com/cafedevvn/
YouTube: https://www.youtube.com/channel/UCE7zpY_SlHGEgo67pHxqIoA/
*/
class Main {
  @Deprecated
  public static void deprecatedMethod() { 
    System.out.println("Deprecated method"); 
  } 
  
  @SuppressWarnings("deprecated")
  public static void main(String args[]) {
    Main depObj = new Main();
    depObj. deprecatedMethod();
  }
}

Đầu ra

Deprecated method

Ở đây, deprecatedMethod() đã được đánh dấu là không dùng nữa và sẽ đưa ra cảnh báo trình biên dịch khi được sử dụng. Bằng cách sử dụng chú thích @SuppressWarnings(“deprecated”), chúng ta có thể tránh các cảnh báo của trình biên dịch.

1.4. @SafeVarargs

chú thích @SafeVarargs khẳng định rằng phương thức chú thích hoặc constructor không thực hiện hoạt động không an toàn trên varargs của nó (số biến của tham số).

Chúng ta chỉ có thể sử dụng chú thích này trên các phương thức hoặc hàm tạo không thể bị ghi đè. Điều này là do các phương thức ghi đè chúng có thể thực hiện các hoạt động không an toàn.

Trước Java 9, chúng ta chỉ có thể sử dụng chú thích này trên các phương thức cuối cùng hoặc phương thức tĩnh vì chúng không thể bị ghi đè. Bây giờ chúng ta cũng có thể sử dụng chú thích này cho các phương thức riêng tư.

Ví dụ 4: Ví dụ về chú thích @SafeVarargs

import java.util.*;

class Main {

  private void displayList(List<String>... lists) {
    for (List<String> list : lists) {
      System.out.println(list);
    }
  }

  public static void main(String args[]) {
    Main obj = new Main();

    List<String> universityList = Arrays.asList("Tribhuvan University", "Kathmandu University");
    obj.displayList(universityList);

    List<String> programmingLanguages = Arrays.asList("Java", "C");
    obj.displayList(universityList, programmingLanguages);
  }
}

Cảnh báo

Type safety: Potential heap pollution via varargs parameter lists
Type safety: A generic array of List<String> is created for a varargs 
 parameter

Đầu ra

Note: Main.java uses unchecked or unsafe operations.
[Tribhuvan University, Kathmandu University]
[Tribhuvan University, Kathmandu University]
[Java, C]

Ở đây, chỉ định một đối số có độ dài thay đổi của kiểu . Điều này có nghĩa là phương thức có thể không có hoặc nhiều đối số. List …

Chương trình trên biên dịch không có lỗi nhưng đưa ra cảnh báo khi chú thích @SafeVarargs không được sử dụng.

Khi chúng ta sử dụng chú thích @SafeVarargs trong ví dụ trên,

@SafeVarargs
 private void displayList(List<String>... lists) { ... }

Chúng ta nhận được cùng một đầu ra nhưng không có bất kỳ cảnh báo nào. Các cảnh báo bỏ chọn cũng bị loại bỏ khi chúng ta sử dụng chú thích này.

1.5. @F FunctionInterface

Java 8 lần đầu tiên giới thiệu chú thích @FunctionalInterface này . Chú thích này chỉ ra rằng khai báo kiểu mà nó được sử dụng là một hàm interface. Một hàm interface chỉ có thể có một phương thức trừu tượng.

Ví dụ 5: Ví dụ về chú thích @F FunctionInterface

@FunctionalInterface
public interface MyFuncInterface{
  public void firstMethod(); // this is an abstract method
}

Nếu chúng ta thêm một phương thức trừu tượng khác, giả sử

@FunctionalInterface
public interface MyFuncInterface{
  public void firstMethod(); // this is an abstract method
  public void secondMethod(); // this throws compile error
}

Bây giờ, khi chúng ta chạy chương trình, chúng ta sẽ nhận được cảnh báo sau:

Unexpected @FunctionalInterface annotation
@FunctionalInterface ^ MyFuncInterface is not a functional interface
multiple non-overriding abstract methods found in interface MyFuncInterface

Không bắt buộc phải sử dụng chú thích @FunctionalInterface. Trình biên dịch sẽ coi bất kỳ giao diện nào đáp ứng định nghĩa FunctionalInterface là FunctionalInterface.

Chúng ta sử dụng chú thích này để đảm bảo rằng giao diện chức năng chỉ có một phương thức trừu tượng.

Tuy nhiên, nó có thể có bất kỳ số lượng các phương thức mặc định và tĩnh vì chúng có một phần triển khai.

@FunctionalInterface
public interface MyFuncInterface{
  public void firstMethod(); // this is an abstract method
  default void secondMethod() { ... } 
  default void thirdMethod() { ... } 
}

2. Chú thích tùy chỉnh

Cũng có thể tạo các chú thích tùy chỉnh của riêng chúng ta.

Cú pháp của nó là:

[Access Specifier] @interface<AnnotationName> {         
  DataType <Method Name>() [default value];
}

Đây là những gì bạn cần biết về chú thích tùy chỉnh:

  • Chú thích có thể được tạo bằng cách sử dụng @interface theo sau là tên chú thích.
  • Chú thích có thể có các phần tử trông giống như các phương thức nhưng chúng không có phần triển khai.
  • Giá trị mặc định là tùy chọn. Các tham số không được có giá trị null.
  • Kiểu trả về của phương thức có thể là kiểu nguyên thủy, enum, chuỗi, tên lớp hoặc mảng của những kiểu này.

Ví dụ 6: Ví dụ về chú thích tùy chỉnh

@interface MyCustomAnnotation {
  String value() default "default value";
}

class Main {
  @MyCustomAnnotation(value = "programiz")
  public void method1() {
    System.out.println("Test method 1");
  }

  public static void main(String[] args) throws Exception {
    Main obj = new Main();
    obj.method1();
  }
}

Đầu ra

Test method 1

3. Chú thích meta

Chú thích meta là chú thích được áp dụng cho các chú thích khác.

3.1. @Retention

Các chú thích @Retention định mức lên đến đó chú thích sẽ có sẵn.

Cú pháp của nó là:

@Retention(RetentionPolicy)

Có 3 loại chính sách lưu giữ:

  • RetentionPolicy.SOURCE – Chú thích chỉ có sẵn ở cấp nguồn và bị trình biên dịch bỏ qua.
  • RetentionPolicy.CLASS – Chú thích có sẵn cho trình biên dịch tại thời điểm biên dịch, nhưng bị Máy ảo Java (JVM) bỏ qua.
  • RetentionPolicy.RUNTIME – Chú thích có sẵn cho JVM.

Ví dụ,

@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomAnnotation{ ... }

3.2. @Documented

Theo mặc định, các chú thích tùy chỉnh không có trong tài liệu Java chính thức . Để đưa chú thích của chúng ta vào tài liệu Javadoc, chúng ta sử dụng chú thích @Documented.

Ví dụ,

@Documented
public @interface MyCustomAnnotation{ ... }

3.3. @Target

Chúng ta có thể hạn chế áp dụng chú thích cho các mục tiêu cụ thể bằng cách sử dụng chú thích @Target.

Cú pháp của nó là:

@Target(ElementType)

Có thể ElementType có một trong các loại sau:

Loại nguyên tốMô tả
ElementType.ANNOTATION_TYPELoại chú thích
ElementType.CONSTRUCTORNgười xây dựng
ElementType.FIELDTrường nào đó
ElementType.LOCAL_VARIABLEBiến cục bộ
ElementType.METHODPhương thức
ElementType.PACKAGEGói
ElementType.PARAMETERTham số
ElementType.TYPEBất kỳ phần tử nào của lớp

Ví dụ,

@Target(ElementType.METHOD)
public @interface MyCustomAnnotation{ ... }

Trong ví dụ này, chúng ta đã giới hạn việc sử dụng chú thích này chỉ cho các phương thức.

Lưu ý: Nếu loại đích không được định nghĩa, chú thích có thể được sử dụng cho bất kỳ phần tử nào.

3.4. @@Inherited

Theo mặc định, một kiểu chú thích không thể được kế thừa từ một lớp cha. Tuy nhiên, nếu chúng ta cần kế thừa chú thích từ lớp cha sang lớp con, chúng ta sử dụng chú thích @Inherited.

Cú pháp của nó là:

@Inherited

Ví dụ,

@Inherited
public @interface MyCustomAnnotation { ... }

@MyCustomAnnotation
public class ParentClass{ ... }

public class ChildClass extends ParentClass { ... }

3.5. @Repeatable

Một chú thích đã được đánh dấu @Repeatable có thể được áp dụng nhiều lần cho cùng một khai báo.

@Repeatable(Universities.class)
public @interface University {
  String name();
}

Giá trị được định nghĩa trong chú thích @Repeatable là chú thích vùng chứa. Chú thích vùng chứa có một biến giá trị kiểu mảng của chú thích có thể lặp lại ở trên. Đây Universities là loại chú thích có chứa.

public @interface Universities {
  University[] value();
}

Bây giờ, chú thích @University có thể được sử dụng nhiều lần trên cùng một khai báo.

@University(name = "TU")
@University(name = "KU")
private String uniName;

Nếu cần truy xuất dữ liệu chú thích, chúng ta có thể sử dụng API phản chiếu, ánh xạ ở các bài trước.

Để truy xuất giá trị chú thích, chúng ta sử dụng phương thức getAnnotationsByType() hoặc getAnnotations() được định nghĩa trong API phản chiếu.

Cài ứng dụng cafedev để dễ dàng cập nhật tin và học lập trình mọi lúc mọi nơi tại đây.

Nguồn và Tài liệu tiếng anh tham khảo:

Tài liệu từ cafedev:

Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you!