4

以下两个代码示例代表相同的逻辑。检查字符串是否为空,并根据该检查进行分支。第一个示例可以安全编译。第二个产生与 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);
}

来自 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);
}
4

3 回答 3

7

问题应该在于编译器如何解释三元运算符的返回值。您可能想看看JLS 的第 15.25 部分或这个问题(有点相关,因为它通过自动装箱更加复杂,并且它在运行时而不是在编译时引发错误)。

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

于 2012-01-24T15:18:22.673 回答
5

这是因为Collections.emptySet()返回一个 untyped Set。相反,试试这个:

Collections.<String>emptySet()
于 2012-01-24T15:17:20.967 回答
1

Collections.emptySet()被声明为

public static final <T> Set<T> emptySet()

第一个T用于类型推断。第二个getUserRoles实现过于复杂,Java 编译器无法检测到正确的类型。这就是问题的原因。解决方法:

protected Collection<String> getUserRoles(Object context,
            Set<String> mappableRoles) {
    String cookieValue = extractCookieValue(context);
    Collection<String> a = null;
    return cookieValue == null ? a = Collections.emptySet()
            : securityService.getRolesForUser(cookieValue);
}
于 2012-01-24T16:19:12.337 回答