What is wrong with this code?
return -1 == endIndex ? Collections.emptyMap() : makeMap(path.substring(endIndex + 1));
Here's a hint:
private static Map<String, String> makeMap(final String s) { final Map<String, String> map = new HashMap<String, String>(); for (final String pair : split(s, ';')) { final int i = pair.indexOf('='); if (-1 == i) map.put(pair, null); else map.put(pair.substring(0, i), pair.substring(i + 1)); } return map; }
Ok, now do you see? What about now:
public Map<String, String> getServiceSpecifiers() { final String path = uri.getPath(); // Ignore service specifier (e.g., ftp) final int endIndex = path.indexOf(';'); return -1 == endIndex ? Collections.emptyMap() : makeMap(path.substring(endIndex + 1)); }
The return type is Map<String, String>
, and Collections.emptyMap()
is defined as:
public static final <K,V> Map<K,V> emptyMap() { return (Map<K,V>) EMPTY_MAP; }
So what is really the matter? Last clue; this fixes the problem:
if (-1 == endIndex) return Collections.emptyMap(); else return makeMap(path.substring(endIndex + 1));
The problem is generics.
The compiler deduces the bounds correctly in return Collections.emptyMap()
but not when in the three-part expression (X ? Y : Z
). The compiler tries to harmonize the types when evaluating the expression, and this leads to picking the lowest bounds possible, Object
rather than String
. The expression is then returned, but now it no longer meets the bounds for the method and it is a syntax error.
The IF statement does not have the extra bounds deduction, so reduces the empty map to the bounds of the method exactly.
How annoying.
UPDATE: An anonymous commenter pointed out the correct Java syntax to pull this off:
return -1 == endIndex ? Collections.<String, String>emptyMap() : makeMap(path.substring(endIndex + 1));
My C++ blinders kept me from considering this possibility; I tried putting the generic specification in several other places in the statement instead, none of which worked. An interesting construction.
UPDATE: Paul Holser pointed out the right name for this construct: the ternary conditional operator.
2 comments:
This is annoying once and then you get used to it. The way to fix it? Instead of
return -1 == endIndex
? Collections.emptyMap()
: makeMap(path.substring(endIndex + 1));
do this:
return -1 == endIndex
? Collections.<String,String>emptyMap()
: makeMap(path.substring(endIndex + 1));
Hey, thanks! I tried putting the <String, String> in several places but not between the dot add emptyMap(). Cool.
Post a Comment