[英]Java generics with upper bound
说我有以下示例应用程序,我正在使用Java 8。
我的以下课程有一个子课程:
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);
}
}
运行此命令时,出现以下错误:
错误:(
java.util.List<GrantedAuthority>
)Java:不兼容的类型:java.util.List<GrantedAuthority>
无法转换为java.util.Collection<? extends capture#1 of ? extends GrantedAuthority>
java.util.Collection<? extends capture#1 of ? extends GrantedAuthority>
我的问题是,如何将GrantedAuthoritySubClass
对象的集合传递给u.getAuthorities()
返回的集合。 我无法弄清楚,尝试过的各种方法都有很多编译错误。
根据PECS规则,您的authorities
集合是元素的producer
者(因为它使用了extends)。 这意味着该集合只能“产生”或“输出” GrantedAuthority
对象或其子类。 这也意味着您无法将任何东西放入集合中,因为您不知道集合的实际类型。
如果使用super
,则可以将对象放在此处(但无法将它们取出),但是我怀疑通配符是完全不必要的。
您无法编译,因为您不知道获得哪种集合。
您需要将签名更改为
Collection<? super GrantedAuthority> getAuthorities()
这说明了问题(c) Andrey Tyukin :
您尝试使用通配符过于精确(并以这种方式进入泛型。)
基本上,尽量避免使用通配符,并尽可能使用自然继承。 在您的示例中,如下更改您的UserDetails:
public class UserDetails {
Collection<GrantedAuthority> authorities;
public Collection<GrantedAuthority> getAuthorities(){
return authorities;
}
}
...一切都会好的。 特别是,随着自然继承的加入,您可以添加GrantedAuthoritySubClass的实例。
因为UserDetails是Spring安全性的接口,所以您不能更改方法定义。 您不能在您的方法中添加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());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.