Java8 Nullness type qualifiers and Maps [message #1386001] |
Thu, 12 June 2014 20:21 |
Kivanc Muslu Messages: 153 Registered: November 2010 |
Senior Member |
|
|
Hi all,
I am trying to understand (and resolve warnings and errors) how to use nullness type qualifiers (improved nullness annotations in Eclipse) with Maps. Here is an example:
Map<@NonNull String, @NonNull String> map = new HashMap<>();
The above code, defines a hash map where keys and values cannot be null (as expected).
map.put("key", "value"); // works as expected
map.put("key2", null); // raises a warning as expected
for (String key: map.keySet())
key.toString(); // works okay since keys cannot be null.
for (String value: map.valueSet())
value.toString(); // works okay since values cannot be null.
Here is where it gets tricky:
String temp = map.get("key3");
if (temp != null)
temp.toString();
Here, for the "if" check, Eclipse raises a warning saying that the check is redundant. So, for some reason, although Map.get(..) could clearly return null (as with this case), the analysis infers the extended type of "temp" as @NonNull.
Am I missing something simple, or is this an a bug in Eclipse nullness analysis?
Thanks and best regards,
[Updated on: Thu, 12 June 2014 20:24] Report message to a moderator
|
|
|
Re: Java8 Nullness type qualifiers and Maps [message #1386003 is a reply to message #1386001] |
Thu, 12 June 2014 20:41 |
Stephan Herrmann Messages: 1853 Registered: July 2009 |
Senior Member |
|
|
That's a problem in interface Map:
This declaration
must actually be changed to
@Nullable V get(Object key);
If you compile, e.g., HashMap in the existing form, with our null analysis enabled, you get:
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
^^^^
}
Null type mismatch (type annotations): 'null' is not compatible to the free type variable 'V'
Explanation: the current API promises: whatever type you supply for 'V', get() will always return a value of that type. This is a strong promise, which the implementation does not realize (it unduly assumes, that 'V' is always a nullable type), hence the signature should weaken the promise.
best,
Stephan
PS: This leads us to the one big null-related project which I hope to address during the Mars-cycle: https://bugs.eclipse.org/331651
|
|
|
Re: Java8 Nullness type qualifiers and Maps [message #1386004 is a reply to message #1386003] |
Thu, 12 June 2014 20:50 |
Kivanc Muslu Messages: 153 Registered: November 2010 |
Senior Member |
|
|
Hi Stephan,
Thanks for the explanation. I am actually looking forward to the ability to annotate external libraries for nullness analysis, so it is good to hear that this is already in motion.
I think I understand the issue. Do you have a suggestion for a workaround?
At the moment, I decided to declare all maps with @Nullable values although they never contain "null" values. For example,
Map<String, @Nullable String> map = new HashMap<>();
map.put("key", "value");
String temp = map.get("key2");
if (temp != null) // This is okay since values are nullable.
temp.toString();
However, this leads to another (kind of) problem. If I want to use valueSet(), then I need to Suppress Warnings.
for (String value: map.values())
value.toString(); // Raises an issue since value could be "null" (although in my program it never is).
As you can see, I actually lie about the type of the map so that I can get the extra check in the get(..) method. However, this comes with the price that I have to suppress warnings each time I use values(..).
Can you see a better workaround?
Thanks and best regards,
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.03677 seconds