2016-04-26 67 views
1

說我有下面的示例應用程序,我用java 8.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); 
    } 
} 

當我運行此我得到以下錯誤:

Error:(12, 35) java: incompatible types: java.util.List<GrantedAuthority> cannot be converted to java.util.Collection<? extends capture#1 of ? extends GrantedAuthority>

我的問題是,如何傳遞的GrantedAuthoritySubClass對象的集合,通過u.getAuthorities()返回的集合。我無法弄清楚,並且有很多編譯錯誤附加到我嘗試過的各種方式。

+3

什麼在你的例子有通配符的意義呢?看看http://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-arent-javas-generics-implicitly-p?rq=1 – JEY

+0

@JEY這是關於春天彈簧結構如上所述的安全4.0.3和UserDetails類。我只是想提出這個問題而不提這個問題。 – nilan59

+0

只是返回Collection 我沒有看到有通配符的要點。 – JEY

回答

1

因爲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()); 
2

根據PECS規則,您的authorities集合是元素的producer(因爲它使用擴展)。這意味着集合只能「產生」或「輸出」對象或其子類。這也意味着你不能把任何東西放入收藏中,因爲你不知道收藏的實際類型。

如果你使用super你可以把你的對象放在那裏(但你不能把它們拿出來),但我懷疑通配符是完全沒有必要的。

1

你嘗試過確切使用通配符(並進入自己的仿製藥地獄的方式。)

基本上,儘量避免通配符和儘可能使用自然遺產。在你的例子中,改變你的UserDetails如下:

public class UserDetails { 
    Collection<GrantedAuthority> authorities; 

    public Collection<GrantedAuthority> getAuthorities(){ 
     return authorities; 
    } 
} 

......並且一切都會好的。尤其是,您可以添加GrantedAuthoritySubClass的一個實例,作爲自然繼承。

2

你不能編譯,因爲你不知道你得到了什麼樣的集合。

您需要簽名更改爲

Collection<? super GrantedAuthority> getAuthorities() 

這說明了什麼問題(三)Andrey Tyukinenter image description here