Reputation: 8960
I am trying to write an Eclipse External Annotation file for the static inner class Map.Entry. How do I do this?
I created a file named Map$Entry.eea
in the java/util
sub-folder under the folder where all of my External Annotation files are located. Here are the contents of that file.
class java/util/Map$Entry
comparingByKey
<K::Ljava/lang/Comparable<-TK;>;V:Ljava/lang/Object;>()Ljava/util/Comparator<Ljava/util/Map$Entry<TK;TV;>;>;
<K::Ljava/lang/Comparable<-TK;>;V:Ljava/lang/Object;>()L1java/util/Comparator<L1java/util/Map$Entry<T1K;TV;>;>;
comparingByKey
<K:Ljava/lang/Object;V:Ljava/lang/Object;>(Ljava/util/Comparator<-TK;>;)Ljava/util/Comparator<Ljava/util/Map$Entry<TK;TV;>;>;
<K:Ljava/lang/Object;V:Ljava/lang/Object;>(L1java/util/Comparator<-TK;>;)L1java/util/Comparator<L1java/util/Map$Entry<TK;TV;>;>;
comparingByValue
<K:Ljava/lang/Object;V::Ljava/lang/Comparable<-TV;>;>()Ljava/util/Comparator<Ljava/util/Map$Entry<TK;TV;>;>;
<K:Ljava/lang/Object;V::Ljava/lang/Comparable<-TV;>;>()L1java/util/Comparator<L1java/util/Map$Entry<TK;T1V;>;>;
comparingByValue
<K:Ljava/lang/Object;V:Ljava/lang/Object;>(Ljava/util/Comparator<-TV;>;)Ljava/util/Comparator<Ljava/util/Map$Entry<TK;TV;>;>;
<K:Ljava/lang/Object;V:Ljava/lang/Object;>(L1java/util/Comparator<-TV;>;)L1java/util/Comparator<L1java/util/Map$Entry<TK;TV;>;>;
equals
(Ljava/lang/Object;)Z
(L0java/lang/Object;)Z
getKey
()TK;
()TK;
getValue
()TV;
()TV;
setValue
(TV;)TV;
(TV;)TV;
Eclipse still flags a warning on entry.getValue()
in the following code:
Map.Entry<@Nullable String, @NonNull Object> entry;
@NonNull Object value = entry.getValue();
The warning is:
Unsafe interpretation of method return type as '@NonNull' based on the receiver type
'Map.<@NonNull Entry<@Nullable String, @NonNull Object>>'. Type Map.Entry<K, V> doesn't seem
to be designed with null type annotations in mind.
Upvotes: 4
Views: 380
Reputation: 8960
Upgrading to Eclipse Oxygen (4.7.0) build 20170620-1800 resolved the problem. Map$Entry.eea
can be left as is in the question and the compiler warnings happen at the appropriate times. If the Map.Entry
V
is @NonNull
in code, then getValue()
's return type is @NonNull
. If the Map.Entry
V
is @Nullable
in code, then getValue()
's return type is @Nullable
.
The code in the question no longer causes a compiler warning. The following code does (which is expected and desired).
Map.Entry<@NonNull String, @Nullable Object> entry;
...
entry.getValue().toString();
Upvotes: 0
Reputation: 34165
The second line after getValue
must be ()T1V;
instead of ()TV;
for @NonNull
:
class java/util/Map$Entry
getValue
()TV;
()T1V;
For @Nullable
it would be ()T0V;
But because the value of a map entry can be null ("it's also possible that the map explicitly maps the key to null"), there should only be a warning at @NonNull Object value = entry.getValue();
if the type of entry
is Map.Entry<String, @Nullable Object>
but not if the type is Map.Entry<String, @NonNull Object>
. To tell Eclipse that Map.Entry
is designed with null type annotations in mind the java/util/Map$Entry.eea
file must be almost empty:
class java/util/Map$Entry
But be careful, if you do the same for Map
then there would be no warning for @NonNull Object o = map.get("foo");
. You have to annotate all @Nullable
type parameters explicitly:
class java/util/Map
get
(Ljava/lang/Object;)TV;
(Ljava/lang/Object;)T0V;
See also: Eclipse 4.6 New and Noteworthy - Improved null analysis with generics
Upvotes: 2