假设我有以下示例应用程序,我使用的是java。
我有以下具有子类的类:
public class GrantedAuthority { }
public class GrantedAuthoritySubClass extends GrantedAuthority { }
下课是棘手的部分发生的地方:
public class UserDetails {
Collection<? extends GrantedAuthority> authorities;
public Collection<? extends GrantedAuthority> getAuthorities(){
return authorities;
}
}
我的主要方法:
public class Main {
public static void main(String[] args) {
UserDetails u = new UserDetails();
List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();
list.add(new GrantedAuthoritySubClass());
u.getAuthorities().addAll(list);
}
}
当我运行时,我收到以下错误:
错误:(12,35)java:不兼容的类型:
java.util.List<GrantedAuthority>
无法转换为java.util.Collection<? extends capture#1 of ? extends GrantedAuthority>
我的问题是,我如何将GrantedAuthoritySubClass
个对象的集合传递给u.getAuthorities()
返回的集合。我无法解决这个问题,而且我尝试过的各种方法都存在很多编译错误。
答案 0 :(得分:2)
根据PECS规则,您的authorities
集合是producer
元素(因为它使用了扩展)。这意味着该集合只能生成&#34;或&#34;输出&#34; GrantedAuthority
个对象或其子类。这也意味着您无法将任何内容放入集合中,因为您不知道集合的实际类型。
如果您使用super
,您可以将对象放在那里(但是你无法将它们取出),但我怀疑通配符是完全没必要的。
答案 1 :(得分:2)
你无法编译因为你不知道你得到什么样的收藏品。
您需要将签名更改为
Collection<? super GrantedAuthority> getAuthorities()
这说明问题(c)Andrey Tyukin:
答案 2 :(得分:1)
你试图使用通配符过于精确(并让自己陷入泛型 - 地狱般的地狱。)
基本上,尽可能避免使用通配符并使用自然继承。在您的示例中,按如下所示更改UserDetails:
public class UserDetails {
Collection<GrantedAuthority> authorities;
public Collection<GrantedAuthority> getAuthorities(){
return authorities;
}
}
......一切都会好的。特别是,您可以添加GrantedAuthoritySubClass的实例,因为自然继承会启动。
答案 3 :(得分:1)
因为UserDetails是弹簧安全性的接口,所以您无法更改方法定义。您无法使用自己的方法添加GrantedAuthority。但是,在实现中,您可以覆盖getAuthorities以返回与接口定义匹配的集合:
public class UserDetailsImpl implements UserDetails {
private Collection<GrantedAuthority> authorities = new ArrayList<>();
@Override
public Collection<GrantedAuthority> getAuthorities() {
return authorities;
}
}
现在你可以像这样使用它:
UserDetailsImpl u = new UserDetailsImpl();
u.getAuthorities().add(new GrantedAuthority());
也可以使用您自己的GrantedAuthority类型:
public class MyGrantedAuthority extends GrantedAuthority{
}
public class UserDetailsImpl implements UserDetails {
private Collection<MyGrantedAuthority> authorities = new ArrayList<>();
@Override
public Collection<MyGrantedAuthority> getAuthorities() {
return authorities;
}
}
UserDetailsImpl u = new UserDetailsImpl();
u.getAuthorities().add(new MyGrantedAuthority());