2016-06-23 10 views
9

Wyrocznia doc about Wildcards in generics mówiDlaczego nie można użyć symbolu wieloznacznego (?) Jako typu parametru, pola, zmiennej lokalnej lub jako metody zwracania metody?

symbolu wieloznacznego można stosować w różnych sytuacjach: jako typ z parametru, dziedzinie lub zmiennej lokalnej; czasami jako typ zwracający (choć lepiej jest, aby programowanie było bardziej szczegółowe).

Próbowałem wszystkich czterech w poniższej klasie, i dostałem błędy kompilacji na każdym z nich. Czemu? Co ja robię źle?

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

Ponieważ nie jest to poprawna składnia. Nie widzę żadnych leków generycznych, tylko "?". –

+0

Lepiej przeczytaj podrozdziały (https://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html) symboli wieloznacznych w rozdziale ogólnym. Nie można używać symboli wieloznacznych bezpośrednio w celu zastąpienia typów. Zobacz także więcej przykładów dostarczanych przez różne źródła w Internecie. –

Odpowiedz

5

Tutorial strasznie sformułowane. Nie możesz użyć symbolu wieloznacznego do żadnej z wymienionych rzeczy. Można użyć typowego typu z wieloznacznikiem w nim dla tych rzeczy.

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

? postać jest wildcard type argument.

Artykuł zaczyna się

W kodzie generycznego, znak zapytania (?), Zwany wieloznaczny, reprezentuje nieznanego typu.

Jedyne miejsce, w którym można użyć tej składni, jest częścią kodu ogólnego, tj. ogólny typ argumentu. Następne zdanie odnosi się do kodu ogólnego za pomocą symbolu wieloznacznego. Tak więc, na przykład

jako typ parametru

można mieć

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

Or dla

jako zmiennej lokalnej

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

Ale

symbolu wieloznacznego nie jest używana jako argument typu dla rodzajowego metoda inwokacji, rodzajowe tworzenia instancji klasy, lub supertypem.

Nie można używać go jako

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

Warto również zauważyć, że ten sam kod w ostatnim fragmencie byłby ważny, gdyby używał 'T' zamiast"? "Do jego wpisywania. –

+0

We wszystkich tych przykładach,'? 'Nie jest używane jako typ, raczej' Lista 'jest używane jako typ. '?' różni się od 'Listy '. Jestem zdezorientowany: s – Solace

+1

@Solace '?' Jest argumentem typu wieloznacznego (http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1). Nie można go używać poza kontekstem typów ogólnych. –

2

Wildcard może być używany z <> operator w koncepcji generyków wprowadzony w Javie 5, używane do reprezentowania nieznany typ. Generics służy do definiowania klasy z elementem w uogólnionym formacie. Jeśli chcesz zapewnić obiekt, który podczas tworzenia obiektu, użytkownik określi typ elementu, możesz użyć pojęcia generics. Można go używać tylko w przypadku, gdy członek instancji nie może być użyty z pamięcią pamięci stałej statycznej, ponieważ statyczny zostanie przydzielony tylko raz.

Koncepcja wieloznacznika wprowadzona w elementach ogólnych w celu ograniczenia typu nieznanego, powiedzmy, że mam listę z symbolem wieloznacznym i tym rozszerzeniem z użyciem symboli wieloznacznych. Oznacza to, że lista może pracować z liczbami całkowitymi, długimi, krótkimi, bajtowymi, ponieważ rozszerzają one klasę opakowującą Number, ale nie zawierają String jako klasy String, która nie rozszerza klasy opakowania Number.

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

przychodzi do ciebie programu użyłeś złego składnię, jak już wspomniano wieloznaczne mogą być używane z <> operatora.

Mamy nie użycie symboli wieloznacznych podczas tworzenia instancji klasy jak wspomniano poniżej -

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

ale możemy użyć rodzajowych w celu zapewnienia dziedzinie jako Nieznany typ jak I, N, S w pracownika klasa. To rodzaj podamy podczas tworzenia obiektu klasy -

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 jako parametr metoda -

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

Deklarowanie zmiennej lokalnej jako zamiennika -

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

Możemy używać symboli wieloznacznych i generycznych jako metody zwrotu. Oto przykład rodzajowych jak rodzaj powrotnego sposobu -

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

Oto przykład zamiennika jako typ powrotnego metody -

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

Twój ostatni przykład, możesz pokazać za pomocą wieloznacznej karty. –

+0

zaktualizowałem moją odpowiedź. – RCS

1

Wildcards nie ma indywidualnego istnienia. Są one zawsze używane jako parametr typu klas ogólnych Ex: List<? extends Number>. Podam jeden przykład obejmujący wszystkie scenariusze.

Powiązane problemy