Consider the following partial content of an Eclipse project that has null analysis enabled:
Eclipse Mars Release (4.5.0; 20150621-1200) for Windows 64-bit
Oracle JDK 1.8.0_60
package-info.java
@org.eclipse.jdt.annotation.NonNullByDefault
package bar;
Foo.java
package bar;
public class Foo {
public static void main(String[] args) {
}
}
class Base<T> {
private final Class<T> type;
public Base(Class<T> type) {
this.type = type;
}
public Class<T> getType() {
return this.type;
}
}
class Derived extends Base<String> {
public Derived() {
super(String.class); // <-- Null type safety warning here
}
}
Null analysis produces the following warning in the call to the superclass ctor in Derived
:
Null type safety (type annotations): The expression of type 'Class<String>' needs unchecked conversion to conform to '@NonNull Class<@NonNull String>'
What is the correct way to avoid this warning?
The conflict you are seeing is between the type arguments ...
@NonNull String
String
The non-null type argument comes into the picture from
extends Base<String>
, which under the regime of@NonNullByDefault
is expanded toextends Base<@NonNull String>
. From here it percolates all the way up to the super constructor, to render its signature after type argument substitution as(@NonNull Class<@NonNull String>)
. By contrast, the class literal is seen by the compiler as having type@NonNull Class<String>
, which is not compatible.The real solution will come via Bug 477719, see in particular the discussion in comment 3 f.
For the time being (with Eclipse Mars) you may have to reduce the effect of
@NonNullByDefault
so that@NonNull Class<String>
will be accepted. This can be achieved by a more specific @NNBD declaration on top of classDerived
like thisHere we are leveraging the fact, the @NNBD can be fine tuned regarding the locations to which it applies. In this declaration the difference to an argument-less
@NonNullByDefault
lies in omitting the locationTYPE_ARGUMENT
, which means thatString
inextends Base<String>
will no longer be affected like mentioned above. Ergo the super constructor will now have this signature:(@NonNull Class<String>)
and all compiles without warnings.By putting the fine tuned @NNBD on the class
Derived
the scope of this workaround is kept a small as possible.