Строка public static <T> java.util.@Nullable Optional<T> toJavaUtilнаписана так, потому что обычный стиль public static <T> @Nullable java.util.Optional<T> toJavaUtilнедопустим. Это определено в JLS § 9.7.4 :
Это ошибка времени компиляции, если аннотация типа T применяется к типу (или любой части типа) в контексте типа, и T применима в контекстах типа, и аннотация не допустима.
Например, предположим, что тип аннотации TA мета-аннотируется просто @Target(ElementType.TYPE_USE). Условия @TA java.lang.Objectи java.@TA lang.Objectявляются незаконными, потому что простое имя, к которому @TA ближе всего, классифицируется как имя пакета. С другой стороны, java.lang.@TA Objectзаконно.
Объявление типа org.checkerframework.checker.nullness.qual@Nullable:
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
Так что это относится к этому правилу.
То, что эта структура не нарушает выполнение, так как имя пакета java.utilи класса Optionalбыли разделены, можно увидеть, когда мы смотрим на скомпилированный код, используя 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.Optionalэто локальный класс, в который я скопировал код Guava, чтобы получить минимальный пример для де-компиляции)
Как видите, аннотации там больше не существует. Это только маркер для компилятора, который предотвращает предупреждение, когда метод возвращает null (и подсказку для читателей исходного кода), но он не будет включен в скомпилированный код.
Эта ошибка компилятора также относится к таким переменным, как:
private @Nullable2 java.util.Optional<?> o;
Но может стать приемлемым, когда аннотация дополнительно получает целевой тип ElementType.FIELD, как написано в том же предложении JLS:
Если TA дополнительно мета-аннотирован с @Target(ElementType.FIELD), то этот термин @TA java.lang.Objectдопустим в местах, которые являются как декларацией, так и контекстами типа, такими как декларация поля @TA java.lang.Object f;. Здесь @TA считается применимым к объявлению f (а не к типу java.lang.Object), потому что TA применяется в контексте объявления поля.
Nullableони говорят, похожеjavax.annotation, нетjava.util.