Rusty Shackleford Rusty Shackleford - 1 year ago 52
Java Question

Eclipse external null annotation for java.lang.Object#getClass()

I'm using the external null annotation facility available in Eclipse Mars. I'm trying to add an external annotation for

java.lang.Object#getClass()
but can't seem to get the signature right. I've tried the following variations:

@NonNull Class<?> getClass() [()L1java/lang/Class<*>;]
@NonNull Class<@NonNull ?> getClass() [()L1java/lang/Class<*1>;]


but continue to get a warning when passing the result of invoking
getClass()
to a method that accepts an instance of
Class<?>
, where that parameter is annotated with
@NonNull
.

Below are the relevant files from a minimal Eclipse Mars project that reproduces the issue (this example uses the first null annotation variation above, but I also get the same warning when using the second variation):

Eclipse Mars Release (4.5.0; 20150621-1200) for Windows 64-bit

Oracle JDK 1.8.0_60

src/bar/Foo.java

package bar;

public class Foo {
private static void printType(Class<?> type) {
System.out.println(type.getName());
}

public static void main(String[] args) {
Foo foo = new Foo();
printType(foo.getClass());
}
}


src/bar/package-info.java

@org.eclipse.jdt.annotation.NonNullByDefault
package bar;


annotations/java/lang/Object.eea

class java/lang/Object
getClass
()Ljava/lang/Class<*>;
()L1java/lang/Class<*>;


.settings/org.eclipse.jdt.core.prefs (partial)

eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled
org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=warning
org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
...
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
...
org.eclipse.jdt.core.compiler.compliance=1.8
...
org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled
...
org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
org.eclipse.jdt.core.compiler.problem.nullReference=error
org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
...
org.eclipse.jdt.core.compiler.problem.potentialNullReference=error
...
org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
...
org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled
...
org.eclipse.jdt.core.compiler.source=1.8


.classpath

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="annotationpath" value="/null-annotation-test/annotations"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="org.eclipse.jdt.annotation_2.0.100.v20150311-1658.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>


For the above project, I receive the following warning on line 10 of Foo.java (where
printType
is called):

Null type safety (type annotations): The expression of type 'Class<capture#of ? extends Foo>' needs unchecked conversion to conform to '@NonNull Class<?>'


which is the same warning I get without the external null annotation being present.

How do I correctly create an external null annotation for
java.lang.Object#getClass()
to remove this warning? Or is my problem in the declaration of
printType
?

Answer Source

Louis Wasserman is correct, in terms of type checking there is not one getClass() method, but each class has it's own method with specialized signature. Hence no signature in a .eea file will ever match the actual getClass() methods.

I filed an RFE to put more special knowledge about getClass() into the compiler, so that no external annotations are needed for this beast.

EDIT: This feature has been implemented and will be released with Eclipse 4.6 (Neon).