9

Die Oracle doc about Wildcards in generics sagtWarum kann ich den Platzhalter (?) Nicht als Parametertyp, Feld, lokale Variable oder als Rückgabetyp einer Methode verwenden?

Der Platzhalter kann in einer Vielzahl von Situationen verwendet werden: als die Typ eines Parameters , Feld oder lokale Variable; manchmal als Rückgabetyp (obwohl es besser Programmierpraxis ist, genauer zu sein).

Ich habe alle vier in der folgenden Klasse ausprobiert, und Compiler Fehler auf jedem. Warum? Was mache ich falsch?

public class MainClass { 
    private ? instanceFieldWithWildCardType;//ERROR 
    private static ? staticFieldWithWildCardType;//ERROR 

    private void methodWithWildCardParam(? param) {}//ERROR 

    private void methodWithWildCardLocalVariable() { 
     ? localVariableWithWildCardType;//ERROR 
    } 

    private ? methodWithWildCardReturnType() {//ERROR 
     return null; 
    } 

    private void methodWithWildCardParam(? param) {}//ERROR 

} 
+1

Weil das keine gültige Syntax ist. Ich sehe keine Generika, nur '?' S. –

+0

Lesen Sie besser die Unterabschnitte (https://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html) von Platzhaltern im generischen Kapitel. Sie können die Platzhalter nicht direkt zum Ersetzen der Typen verwenden. Siehe auch viele weitere Beispiele, die von verschiedenen Quellen im Internet bereitgestellt werden. –

Antwort

5

Das Tutorial schrecklich formuliert ist. Sie können keinen Platzhalter für eines der aufgeführten Dinge verwenden. Sie können einen generischen Typ mit einem Platzhalter für diese Dinge verwenden.

public class Example { 
    ? field1;  // invalid 
    List<?> field2; // valid 

    private ? method1(? param) {return param;}    // invalid 
    private List<?> method2(List<?> param) {return param;} // valid 

    private void method3() { 
     ? var1;  // invalid 
     List<?> var2; // valid 
    } 
} 
8

Der ? Charakter ist die wildcard type argument.

Der Artikel beginnt mit

In generischem Code, das Fragezeichen (?), Die so genannte Wildcard, stellt einen unbekannten Typ.

Der einzige Ort, an dem Sie diese Syntax verwenden können, ist als Teil des generischen Codes, dh. ein generisches Argument. Der nächste Satz bezieht sich auf generischen Code, der den Platzhalter verwendet. So zum Beispiel

als Typ eines Parameters

könnten Sie haben

public static void shuffle(List<?> list) { 

Oder

als lokale Variable

public void method() { 
    List<?> list = Arrays.asList(1, 2, 3); 
    Collections.shuffle(list); 
    System.out.println(list); 
} 

Aber

Der Platzhalter wird nie als Typargument für einen generischen Methode Aufruf, eine generische Klasseninstanz Schöpfung oder einen übergeordneten Typ verwendet.

Sie können es nicht als

Arrays.<?>asList(1, "", '5'); 
List<?> list = new ArrayList<?>(); 
... 
public class MyList implements List<?> {/* whatever */} 
+0

Beachten Sie auch, dass der gleiche Code im letzten Ausschnitt gültig wäre, wenn er 'T' anstatt' '' für seine Eingabe verwendet –

+0

In all diesen Beispielen wird '?' Nicht als Typ, sondern als Liste verwendet 'wird als ein Typ verwendet. '?' unterscheidet sich von 'List '. Ich bin verwirrt: s – Solace

+1

@Solace '?' Ist das [Wildcard-Typ-Argument] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1). Es kann nicht außerhalb des Kontextes generischer Typen verwendet werden. –

2

können Wildcard mit <> Operator in einem Generika-Konzept in Java 5, verwendet eingeführt verwendet werden, um unbekannte Art darstellen. Generics wird verwendet, um eine Klasse mit einem Element im verallgemeinerten Format zu definieren.Wenn Sie eine Funktion bereitstellen möchten, die beim Erstellen des Objekts den Benutzer angibt, geben Sie den Typ des Elements an, und Sie können das Konzept der Generika verwenden. Es kann nur für das Instanzelement verwendet werden, das nicht mit dem statischen Element verwendet werden kann, da Speicher für statische Daten nur einmal zugewiesen wird.

Wildcard-Konzept in Generika eingeführt, um unknow type zu beschränken, sagen wir, ich habe Liste, die Platzhalter hat und diese Platzhalter erweitern Nummer Wrapper-Klasse. Das bedeutet, dass list mit Integer, Long, Short, Byte arbeiten kann, weil sie die Number-Wrapper-Klasse erweitern, aber nicht mit String, da die String-Klasse die Number-Wrapper-Klasse nicht erweitert.

List<? extends Number> lt = new ArrayList<>(); 

Sie Programm kommen, haben Sie falsche Syntax verwendet, wie ich Wildcard erwähnt haben, können mit <> Operator verwendet werden.

Wir nicht Verwendung Platzhalter während der Instanziierung Klasse wie unten erwähnt -

List<?> lt = new ArrayList<?>(); 

aber wir können Generika verwenden Sie das Feld als unbekannte Art wie I, N, S in Mitarbeiter zu schaffen, Klasse. Es ist Art stellen wir dabei die Aufgabe der Klasse erstellen -

class Employee<I,N,S> 
{ 
    I eid; 
    N empName; 
    S empSalary; 
} 

class Name 
{ 
    String firstName; 
    String middleName; 
    String lastName; 
} 

class salary 
{ 
    double basic; 
    float it; 
    float tds; 
    double netsal; 
} 

class CustomId 
{ 
    int empId; 
    String department; 
    int branchId; 
} 

main method 
------------ 

    Employee<Integer,String,Double> emp = new Employee<>(); 
    Employee<String,Name,Salary> emp2 = new Employee<>(); 
    Employee<CustomId,String,Salary> emp3 = new Employee<>(); 

Wildcard als Methodenparameter -

public void sortList(List<?> lt) 
{ 
    // code to sort the list whether it is integer, String etc 
} 
call sortList() method 
----------------------- 
List<String> lt = new List<>(); 
lt.add("sss"); 
lt.add("aaa"); 
sortList(lt); 

List<Integer> lt = new List<>(); 
lt.add(11); 
lt.add(12); 
sortList(lt); 

lokale Variable als Platzhalter Deklarieren -

List<?> lt = new ArayList<String>(); 
List<?> lt = new ArayList<Integer>(); 

Wir können Wildcard und Generics als Rückgabetyp der Methode verwenden. Hier ist das Beispiel von Generika als Rückgabetyp Methode -

public T getName(ClassName obj, Key key) 
{ 
    return (Type<T>)obj.getType(Key); 
} 

Hier ist das Beispiel des Wildcard als Rückgabetyp Methode -

List<?> method(List<?> data) 
    { 
     return data;  
    } 
+0

Ihr letztes Beispiel, das Sie mit Wildcard zeigen konnten. –

+0

aktualisierte meine Antwort. – RCS

1

Wildcards haben keine individuelle Existenz. Sie werden immer als Typparameter für generische Klassen verwendet. Beispiel: List<? extends Number>. Ich gebe ein Beispiel für alle Szenarien.

import java.util.ArrayList; 
import java.util.List; 

class A{ 

    // I have not make use of this anywhere in this example 
    List<? extends Number> l1; //Field; 

    //Just taking l2 as parameter 
    //Wont be using it also 
    //Just tp show wildcard with generic as parameter 
    public List<? extends Number> operate(List<? extends Number> l2){ //As return Type; Not recommended Approach 

     List<Integer> list = new ArrayList<>(); 
     list.add(new Integer(6)); 
     return list; 
    } 

} 



public class Main { 

    public static void main(String[] args) { 

     List<? extends Number> ar = new ArrayList<Integer>(); //Local Variable 
     A obj = new A(); 
     System.out.println(obj.operate(ar)); 
    } 
} 
Verwandte Themen