为什么以及如何通过编译器对这两个条件进行不同的处理?

Mik*_*key 4 java generics type-inference conditional-operator type-bounds

以下两个代码示例表示相同的逻辑.检查字符串是否为null并根据该检查进行分支.第一个样本安全编译.第二个产生与Java泛型相关的类型不匹配错误.我的问题似乎很简单,但它让我望而却步.为什么编译器对这两个语句的处理方式不同?我怎样才能更好地了解这里发生了什么?

/* 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);
}
Run Code Online (Sandbox Code Playgroud)

来自Eclipse的编译器错误.

Type mismatch: cannot convert from Set<capture#1-of ? extends Object> to Collection<String>

根据要求,这是SecurityService接口的相关部分.

public interface SecurityService {
    public Set<String> getRolesForUser(String userId);
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ace 7

问题应该在于编译器如何解释三元运算符的返回值.您可能希望查看JLS的第15.25部分或此问题(有点相关,因为它通过自动装箱甚至更复杂,并且它在运行时而不是在编译时抛出错误).

希望这能让你朝着正确的方向前进.


小智 5

这是因为Collections.emptySet()返回一个无类型的Set.相反,试试这个:

Collections.<String>emptySet()
Run Code Online (Sandbox Code Playgroud)