The following two code samples represent the same logic. Check to see if a string is null and branch based upon that check. The first sample compiles safely. The second produces a type mismatch error related to Java generics. My question seems simple enough, but it eludes me. Why does the compiler treat these two statements differently? How can I better understand what's going on here?
/* compiles cleanly */
protected Collection<String> getUserRoles(Object context,
Set<String> mappableRoles) {
String cookieValue = extractCookieValue(context);
if (cookieValue != null) {
return securityService.getRolesForUser(cookieValue);
} else {
return Collections.emptySet();
}
}
/* produces a compiler error */
protected Collection<String> getUserRoles(Object context,
Set<String> mappableRoles) {
String cookieValue = extractCookieValue(context);
return cookieValue == null ? Collections.emptySet()
: securityService.getRolesForUser(cookieValue);
}
The compiler error from Eclipse.
Type mismatch: cannot convert from Set<capture#1-of ? extends Object> to Collection<String>
As requested, here's the relevant portion of the SecurityService interface.
public interface SecurityService {
public Set<String> getRolesForUser(String userId);
}
The problem should reside in how the compiler interprets the return value of the ternary operator. You might want to take a look at part 15.25 of the JLS or at this question (kinda related because it's even further complicated by autoboxing and it throws an error at runtime instead of at compile time).
Hope this puts you on the right direction.