Ý nghĩa của java.util. @ Nullable là gì?


56

Tôi đang đọc mã của Guava nơi tôi tìm thấy chú thích java.util.@Nullabletrong một số mã. Tôi biết ý nghĩa của nó @Nullable, nhưng tôi không hiểu cái này. Cụ thể, tôi không thể tìm thấy một lớp được gọi Nullabletrong gói java.util. Xin vui lòng, ai đó cho tôi biết ý nghĩa của việc này java.util.@Nullable:

public static <T> java.util.@Nullable Optional<T> toJavaUtil(
    @Nullable Optional<T> googleOptional) {
  return googleOptional == null ? null : googleOptional.toJavaUtil();
}

4
@PaulRooney Tôi không nghĩ vậy. Các Nullablehọ đang nói về có vẻ là trong javax.annotation, không java.util.
Joseph Sible-Phục hồi Monica

3
Tôi tự hỏi nếu điều này có thể chỉ là một cú pháp Java kỳ lạ. Cụ thể, điều này về cơ bản chỉ có nghĩa public static <T> @Nullable java.util.Optional<T> toJavaUtil, nhưng Java chỉ không cho phép bạn viết theo cách đó?
Joseph Sible-Phục hồi Monica

1
@JosephSible public static <T> @Nullable java.util.Optional<T> toJavaUtilthực sự là không thể, nhưng không có lý do gì để sử dụng FQN Optionalkhi việc nhập đã tồn tại.
Tom

6
@Tom Có một Optionalphạm vi khác ở đó.
Joseph Sible-Phục hồi Monica

2
cảm ơn các bạn, tôi đã tìm thấy cái này trong Checker Framework. @Nullable java.util.List The correct Java syntax to write an annotation on a fully-qualified type name is to put the annotation on the simple name part, as in java.util.@Nullable List. But, it’s usually better to add import java.util.List to your source file, so that you can just write @Nullable List.
SetDaemon

Câu trả lời:


37

Dòng public static <T> java.util.@Nullable Optional<T> toJavaUtilnày được viết như thế này, bởi vì kiểu thông thường public static <T> @Nullable java.util.Optional<T> toJavaUtilkhông hợp lệ. Điều này được định nghĩa trong JLS §9.7.4 :

Đó là lỗi thời gian biên dịch nếu chú thích loại T áp dụng cho một loại (hoặc bất kỳ phần nào của loại) trong ngữ cảnh loại và T được áp dụng trong ngữ cảnh loại và chú thích không được chấp nhận.

Ví dụ: giả sử một loại chú thích TA được chú thích bằng meta @Target(ElementType.TYPE_USE). Các điều khoản @TA java.lang.Objectjava.@TA lang.Objectbất hợp pháp vì tên đơn giản mà @TA gần nhất được phân loại là tên gói. Mặt khác, java.lang.@TA Objectlà hợp pháp.

Khai báo kiểu org.checkerframework.checker.nullness.qual@Nullablelà:

@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})

Vì vậy, nó đang áp dụng cho quy tắc này.

Cấu trúc này không phá vỡ sự thực thi, vì java.utiltên gói và tên lớp Optionalđược phân tách, có thể được nhìn thấy khi chúng ta xem mã được biên dịch bằng cách sử dụng javap -c [compiled class name]:

class just.a.test.Main {
  just.a.test.Main();
    Code:
       0: aload_0
       1: invokespecial #1          // Method java/lang/Object."<init>":()V
       4: return

  public static <T> java.util.Optional<T> toJavaUtil(blub.Optional<T>);
    Code:
       0: aload_0
       1: ifnonnull     8
       4: aconst_null
       5: goto          12
       8: aload_0
       9: invokevirtual #2          // Method blub/Optional.toJavaUtil:()Ljava/util/Optional;
      12: areturn
}

( blub.Optionallà một lớp cục bộ nơi tôi đã sao chép mã Guava, để lấy một ví dụ tối thiểu để khử / biên dịch)

Như bạn có thể thấy, chú thích không còn tồn tại ở đó nữa. Nó chỉ là một điểm đánh dấu cho trình biên dịch để ngăn cảnh báo khi phương thức trả về null (và một gợi ý cho các trình đọc mã nguồn), nhưng nó sẽ không được bao gồm trong mã được biên dịch.


Lỗi trình biên dịch này cũng áp dụng cho các biến như:

private @Nullable2 java.util.Optional<?> o;

Nhưng có thể trở nên chấp nhận được khi chú thích bổ sung thêm loại mục tiêu ElementType.FIELD, như được viết trong cùng một mệnh đề JLS:

Nếu TA được thêm chú thích meta @Target(ElementType.FIELD), thì thuật ngữ @TA java.lang.Objectnày là hợp pháp ở các vị trí có cả bối cảnh khai báo và loại, chẳng hạn như khai báo trường @TA java.lang.Object f;. Ở đây, @TA được coi là áp dụng cho khai báo f (và không áp dụng cho kiểu java.lang.Object) vì TA được áp dụng trong ngữ cảnh khai báo trường.


11

Khi sử dụng chú thích, đây là cú pháp được sử dụng khi bạn muốn viết tên đủ điều kiện cho loại, thay vì thêm câu lệnh nhập.

Trích dẫn từ hướng dẫn khung kiểm tra :

Cú pháp Java chính xác để viết chú thích vào tên loại đủ điều kiện là đặt chú thích vào phần tên đơn giản, như trong java.util. @ Nullable List. Nhưng, tốt hơn hết là thêm nhập java.util.List vào tệp nguồn của bạn, để bạn có thể viết Danh sách @Nullable.

Nó cũng được đề cập ở trang 2 của đặc tả JSR308 có thể được tải xuống ở đây . Nó nói rằng:

Chú thích loại xuất hiện trước tên đơn giản của loại, như trong @NonNull String hoặc java.lang. @ NonNull String.


6

Bit lạ ở đây thực sự là cú pháp lạ để áp dụng ElementType.TYPE_USEchú thích -targeted. Nếu bạn kiểm tra tài liệu của Nullable , bạn sẽ thấy mục tiêu lạ:

...
@Target(value={TYPE_USE,TYPE_PARAMETER})
<public @interface Nullable
...

Chú thích này được sử dụng ngay trước tên đơn giản của loại chú thích, giống như trong cả hai điều sau đây:

public static <T> @Nullable Optional<T> toJavaUtil
public static <T> java.util.@Nullable Optional<T> toJavaUtil

Tôi không biết việc sử dụng loại mục tiêu này là gì, vì vậy sau khi đọc nhanh, tôi đã nhận được ví dụ đơn giản này, chọn ra siêu dữ liệu loại trả về bằng cách sử dụng chú thích có mục tiêu đó:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@interface InterceptedReturnValue {
    boolean value() default true;
}

Và xử lý nó bằng cách sử dụng:

public java.lang.@InterceptedReturnValue(true) String testMethod(String param) {
    return null;
}

public @InterceptedReturnValue(false) String testMethod(int param) {
    return null;
}

public static void main(String[] args) throws Exception {
    Method m = Main.class.getDeclaredMethod("testMethod", String.class);
    if(m.getAnnotatedReturnType().isAnnotationPresent(InterceptedReturnValue.class)) {
        InterceptedReturnValue config = m.getAnnotatedReturnType()
                .getAnnotation(InterceptedReturnValue.class);

        if(config.value()) {
            //logging return value enabled
        }
    }
}

Tôi chắc chắn nhiều khung công tác hữu ích, chẳng hạn như công cụ kiểm tra, sử dụng hợp lý nhất ElementType.TYPE_USE

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.