2012-04-13 2 views
2

Ich habe diese 2-Schnittstellen zu gewährleisten:Versuchen N-Parameter in der Karte mit Generika

public interface Attribute<N> { 

    Class<N> getAttributeType(); 
} 

public interface FieldSubscriber<N> { 

    void notifySubscriber(N value); 
} 

jetzt ich eine FieldRelationsManager Klasse, die verschiedenen Arten von Feldern Beziehungen Handler, zum Beispiel wird es eine Abonnement-Funktion bietet, wo ein FieldSubscriber könnte abonnieren, um über die Wertänderung eines Werthalters informiert zu werden. Damit der Manager eine Liste der FieldSubscribers für ein bestimmtes Attribut benötigt, muss er wissen, welche Subcriptions er benachrichtigen muss. So FieldRelationsManager wie folgt aussieht:

public class FieldRelationsManager { 

    private Map<Attribute<?>, List<FieldSubscriber<?>>> subscribers; 
    ..... 
    ..... 
} 

um sicherzustellen, dass der Client des Managers ein FieldSubscriptor für das gleiche N auf das Attribut liefert, ich versuche, wie ein Verfahren zu schaffen:

public <N> void subscribe(Attribute<N> attr, FieldSubscriber<N> subscriber){ 

    if(subscribers==null){ 
     subscribers=new HashMap<Attribute<?>, List<FieldSubscriber<?>>>(); 
    } 
    List<FieldSubscriber<N>> list=subscribers.get(attr); 
    .... 
    .... 
} 

Dies wird nicht kompiliert, weil: subscribers.get (attr); kehrt:

List<FieldSubscriber<?>> 

und nicht gegossen werden kann:

List<FieldSubscriber<N>> 

so die Frage ist, gibt es eine andere Möglichkeit, ich dies, um Code könnte, um sicherzustellen, dass N-Parameter gleich sein würden?

+2

Wenn Sie Generics in Java verwenden, wird die Art der Information gelöscht und ist zur Laufzeit nicht verfügbar. Es gibt keine elegante Möglichkeit, dies zu umgehen. Wenn Sie die Typinformation wirklich benötigen, müssen Sie explizit verlangen, dass der Client-Code ein 'Class'-Argument übergibt. – jpm

Antwort

2

Java Generics Informationen verwendet werden. Sobald das Programm ausgeführt wird, arbeitet Java mit einer Liste von Objekten.

So Ihre Methode wie folgt definieren, mit <N>, ohne Probleme

public <N> void subscribe(Attribute<N> attr, FieldSubscriber<N> subscriber) { 

Auf diese Weise können Sie sicher sein, dass Compiler bei der Kompilierung überprüft, dass die Methode in Ihrem Code immer mit genannt wird beide N Typ Argumente.

Aber innerhalb der Methode der Arbeit mit der Liste, <?> mit

List<FieldSubscriber<?>> list = subscribers.get(attr); 
if (list == null) { 
    list = new ArrayList<FieldSubscriber<?>>(); 
    subscribers.put(attr, list); 
} 
list.add(subscriber); 

Einmal innerhalb der Methode können Sie arbeiten und sicher sein, dass die Argumente der Art, die Sie wünschen.

0

Sie könnten versuchen: nur bei der Kompilierung

public <N extends Iface> void subscribe(Attribute<N> attr, 
    FieldSubscriber<N> subscriber) 
{ 
    if(subscribers==null){  
    subscribers=new HashMap<Attribute<? extends Iface>, 
     List<FieldSubscriber<? extends Iface>>>();  
    }  
    List<FieldSubscriber<? extends Iface>> list=subscribers.get(attr); 
    list.add(subscriber); 
    ....  
    ....  
} 

public interface Attribute<N> { 
    Class<N> getAttributeType(); 
} 

public interface FieldSubscriber<N> { 
    void notifySubscriber(N value); 
} 

public class FieldRelationsManager { 
    private Map<Attribute<? extends Iface>, 
     List<FieldSubscriber<? extends Iface>>> subscribers; 
    ..... 
    ..... 
}