2016-08-10 3 views
4

Im Java tutorials, es wird manchmal geschrieben, Dinge wie diese erklären:Warum eine Variable als Platzhalter Typ

Set<?> unknownSet = new HashSet<String>(); 

Während ich, ich frage mich, verstehen die Vorteile der Verwendung von Typparametern und Platzhalter in Klassendefinitionen und Methoden die folgenden:

  • Was sind die Vorteile einer Variablen geben einen Typ, der einen Platzhalter umfasst?
  • Im wirklichen Leben, tun Leute das, und wann?
+0

Eng verwandt: http://stackoverflow.com/questions/18176594/when-to-use-generic-methods-and-when-to-use-wild-card und http://stackoverflow.com/ Fragen/2922811/whats-the-purpose-behind-wildcards-und-wie-sind-sie-anders-von-Generika – Tunaki

+0

Platzhalter sind nur in Methodenparameterdeklarationen wirklich nützlich, da sie den Bereich akzeptabler Parametertypen vergrößern. Platzhalter in Rückgabetypen erschweren den Benutzern Ihrer Klasse das Leben (oder eher unordentlich); Wildcards in Ihren lokalen Variablen sind nicht notwendig (außer um die Ergebnisse von Wildcard-Rückgabe-Methoden zu akzeptieren). Um zu zitieren * Effektive Java 2nd Ed *, "Wenn der Benutzer einer Klasse über Wildcard-Typen denken muss, gibt es wahrscheinlich etwas falsch mit der API der Klasse." –

Antwort

2

Wildcards sind nur dann wirklich in Methodenparameter Erklärungen nützlich, da sie den Bereich der akzeptablen Parametertypen erhöhen, zum Beispiel:

void original(List<Number> list) { /* ... */ } 
void withUpperWildcard(List<? extends Number> list) { /* ... */ } 
void withLowerWildcard(List<? super Number> list) { /* ... */ } 

original(new ArrayList<Number>());  // OK. 
original(new ArrayList<Integer>());  // Compiler-error. 
original(new ArrayList<Object>());  // Compiler-error. 

withUpperWildcard(new ArrayList<Number>()); // OK. 
withUpperWildcard(new ArrayList<Integer>()); // OK. 

withLowerWildcard(new ArrayList<Number>()); // OK. 
withLowerWildcard(new ArrayList<Object>()); // OK. 

Wildcards im Gegenzug Arten das Leben schwer machen (oder, besser gesagt, chaotisch) für Benutzer Ihrer Klasse, da müssen Sie also entweder sie verbreiten oder explizite Arbeit zu tun, um sie verschwinden zu lassen, zum Beispiel:

List<? extends Number> method() { /* ... */ } 

// Compiler error. 
List<Number> list1 = method(); 
// OK, but yuk! 
List<? extends Number> list2 = method();   
// OK, but the list gets copied. 
List<Number> list3 = new ArrayList<Number>(method()); 

Wildcards in Ihrem lokalen Variablen sind einfach nicht notwendig (außer die Ergebnisse der Wildcard zu akzeptieren -returning Methoden).

Zitat Effective Java 2nd Ed:

Wenn der Benutzer einer Klasse über Wildcard-Typen zu denken hat, gibt es wahrscheinlich mit der Klasse des API etwas nicht stimmt.

2

Das macht in der Tat nicht viel Sinn. Es sei denn, das einzige, was Sie wollen, ist es zu lesen:

Set<?> unknownSet = new HashSet<String>(); 
System.out.println(unknownSet); // prints empty set: [] 
unknownSet.add("salala"); // compile error 

Auf der anderen Seite ist die Diamond Operator Reiniger und ein bisschen mehr nützlich:

Set<String> unknownSet = new HashSet<>(); 
unknownSet.add("salala"); // okay now 
System.out.println(unknownSet); // prints single set: [salala] 

schließlich mit einem generischen Objekttyp können Sie erstellen gemischte Sets. Aber die sind schwer zu debuggen:

Set<Object> unknownSet = new HashSet<>(); 
unknownSet.add("salala"); // adding a String 
unknownSet.add(42); // adding an Integer 
System.out.println(unknownSet); // prints set, sg like this: [42, salala] 
1

Dies ist der Fall von unbounded wildcard.

Es war seine Vorteile erwähnt gibt:

Wenn Sie eine Methode schreiben, die Funktionalität implementiert werden kann in der Objektklasse zur Verfügung gestellt. Wenn der Code Methoden in der generischen Klasse verwendet, die nicht vom Typparameter abhängen. Zum Beispiel List.size oder List.clear. In der Tat ist Klasse so häufig verwendet, da die meisten Methoden der Klasse auf T. hängen nicht

Aber wenn eine Variable deklarieren, ich stimme es nicht etwas mehr nützlich ist, weil Ihre Variable bereits begrenzt wurde von RHS-Seite und tatsächlich können Sie keine String Elemente hinzufügen, wie in der anderen Antwort darauf hingewiesen. Der unbeschränkte Platzhalter ist in Methoden wie dem printList, der in dem oben erwähnten Beispiel verwendet wird, nützlicher.

Verwandte Themen