以下两个代码示例表示相同的逻辑。检查字符串是否为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);
}
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);
}
答案 0 :(得分:7)
问题应该在于编译器如何解释三元运算符的返回值。您可能需要查看part 15.25 of the JLS或此question(有点相关,因为它通过自动装箱更加复杂,并且在运行时而不是在编译时抛出错误。)
希望这会让你朝着正确的方向前进。
答案 1 :(得分:5)
这是因为Collections.emptySet()
会返回无类型的Set
。相反,试试这个:
Collections.<String>emptySet()
答案 2 :(得分:1)
Collections.emptySet()声明为
public static final <T> Set<T> emptySet()
第一个 T 用于Type Inference。第二个 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);
}