Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the meaning of java.util.@Nullable?

Tags:

java

I'm reading the code of Guava where I found the annotation java.util.@Nullable in some code. I know the meaning of @Nullable, but I don't understand this one. In particular, I can't find a class called Nullable in the package java.util. Please, someone tell me what's the meaning of this java.util.@Nullable:

public static <T> java.util.@Nullable Optional<T> toJavaUtil(     @Nullable Optional<T> googleOptional) {   return googleOptional == null ? null : googleOptional.toJavaUtil(); } 
like image 937
SetDaemon Avatar asked Oct 09 '19 03:10

SetDaemon


People also ask

What does nullable mean in Java?

@NullableMethod calls that can return null. Variables (fields, local variables, and parameters), that can be null.

What is the use of @nullable?

You typically use a nullable value type when you need to represent the undefined value of an underlying value type. For example, a Boolean, or bool , variable can only be either true or false . However, in some applications a variable value can be undefined or missing.

How do you create a nullable variable in Java?

... you can use: Boolean myval = null; You can assign it like this: myval = new Boolean(true);

What is the use of @nullable annotation?

On the other hand, if the parameter is mark as @Nullable and we don't add null check inside the function, Android Studio will warn you with lint error and some visual hint. The @NonNull/@Nullable annotation can put in front of functions as well to indicate the return value nullability.


1 Answers

The line public static <T> java.util.@Nullable Optional<T> toJavaUtil is written like this, because the usual style public static <T> @Nullable java.util.Optional<T> toJavaUtil is invalid. This is defined in the JLS §9.7.4:

It is a compile-time error if an annotation of type T applies to a type (or any part of a type) in a type context, and T is applicable in type contexts, and the annotation is not admissible.

For example, assume an annotation type TA which is meta-annotated with just @Target(ElementType.TYPE_USE). The terms @TA java.lang.Object and java.@TA lang.Object are illegal because the simple name to which @TA is closest is classified as a package name. On the other hand, java.lang.@TA Object is legal.

The type declaration of org.checkerframework.checker.nullness.qual@Nullable is:

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

So it is applying to this rule.

That this structure doesn't break the execution, since package java.util and class name Optional were split, can be seen when we look at the compiled code using 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 is a local class where I copied the Guava code in, in order to get a minimal example to de-/compile)

As you can see, the annotation doesn't exist there anymore. It is only a marker for the compiler to prevent a warning when the method returns null (and a hint for the source code readers), but it won't be included in the compiled code.


This compiler error also applies to variables like:

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

But can become acceptable when the annotation additionally gets the target type ElementType.FIELD, as written in the same JLS clause:

If TA is additionally meta-annotated with @Target(ElementType.FIELD), then the term @TA java.lang.Object is legal in locations which are both declaration and type contexts, such as a field declaration @TA java.lang.Object f;. Here, @TA is deemed to apply to the declaration of f (and not to the type java.lang.Object) because TA is applicable in the field declaration context.

like image 197
Tom Avatar answered Sep 20 '22 21:09

Tom