Rusty Shackleford Rusty Shackleford - 7 months ago 8
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

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).

Comments