2016-04-26 7 views
1

sagen, ich habe folgende Beispielanwendung, ich bin mit Java 8.Java Generics mit obere Schranke

I Klasse verfolgt haben, die ein Kind Klasse:

public class GrantedAuthority { } 
public class GrantedAuthoritySubClass extends GrantedAuthority { } 

Nach Klasse ist, wo der schwierige Teil passiert:

public class UserDetails { 

    Collection<? extends GrantedAuthority> authorities; 

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

Meine Hauptmethode:

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); 
    } 
} 

Wenn ich laufe dies ich folgende Fehlermeldung erhalten:

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

Mein Problem ist, wie ich eine Sammlung von GrantedAuthoritySubClass Objekten der Sammlung von u.getAuthorities() zurücktreten kann. Ich kann es nicht herausfinden und es gibt so viele Kompilierungsfehler bei den verschiedenen Möglichkeiten, die ich versucht habe.

+3

was der Punkt Wildcard zu haben in Ihrem Beispiel? werfen Sie einen Blick auf http://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-arent-java-generics-implicitly-p?rq=1 – JEY

+0

@JEY Dies ist über den Frühling -Sicherheit 4.0.3 und UserDetails Klasse im Frühjahr wie oben strukturiert. Ich wollte nur die Frage einfacher machen, ohne das zu erwähnen. – nilan59

+0

nur zurück Sammlung Ich sehe keinen Punkt mit einem Platzhalter. – JEY

Antwort

1

Da UserDetails eine Schnittstelle für Federsicherheit ist, können Sie die Methodendefinition nicht ändern. Sie können nicht mit Ihrer Methode hinzufügen. Doch bei der Umsetzung können Sie die getAuthorities außer Kraft setzen eine Sammlung zurückzugeben, die die Schnittstellendefinition entsprechen:

public class UserDetailsImpl implements UserDetails { 

    private Collection<GrantedAuthority> authorities = new ArrayList<>(); 

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

Und jetzt können Sie es wie folgt verwendet werden:

UserDetailsImpl u = new UserDetailsImpl(); 
u.getAuthorities().add(new GrantedAuthority()); 

Es ist auch möglich, eigene GrantedAuthority zu verwenden Typ wie folgt:

2

Gemäß der PECS Regel ist Ihre authorities Sammlung eine producer von Elementen (da es erweitert verwendet). Dies bedeutet, dass die Sammlung nur GrantedAuthority Objekte oder deren Unterklassen "produzieren" oder "ausgeben" kann. Es bedeutet auch, dass Sie nichts in die Sammlung einfügen können, da Sie den tatsächlichen Typ der Sammlung nicht kennen.

Wenn Sie super verwendet haben, könnten Sie Ihre Objekte dort platzieren (aber Sie konnten sie nicht bekommen), aber ich vermute, dass der Platzhalter völlig unnötig ist.

1

Sie versuchen, zu genau, um die Wildcard (und sich selbst in die Generika-Hölle auf diese Weise.)

Grundsätzlich versuchen Platzhalter zu vermeiden und natürliche Vererbung zu verwenden, wenn möglich. In Ihrem Beispiel ändern Sie Ihre UserDetails wie folgt:

... und alles wird gut. Insbesondere können Sie eine Instanz von GrantedAuthoritySubClass hinzufügen, wenn die natürliche Vererbung eintritt.

2

Sie können nicht kompilieren, weil Sie nicht wissen, welche Art von Sammlung Sie erhalten.

Sie benötigen die Unterschrift

Collection<? super GrantedAuthority> getAuthorities() 

Dies verdeutlicht das Problem (c) Andrey Tyukin zu ändern: enter image description here