2016-06-23 45 views
9

Oracle doc about Wildcards in generics dicePerché non posso usare il carattere jolly (?) Come tipo di parametro, campo, variabile locale o come tipo di ritorno di un metodo?

Il carattere jolly può essere utilizzato in una varietà di situazioni: come tipo di un parametro , campo, o variabile locale; a volte come un tipo di ritorno (anche se è meglio che la pratica di programmazione sia più specifica).

Ho provato tutti e quattro nella seguente classe e ho ricevuto errori di compilazione su ognuno di essi. Perché? Che cosa sto facendo di sbagliato?

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

Perché non è una sintassi valida. Non vedo generici, solo '' s. –

+0

Leggere meglio le sottosezioni (https://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html) di caratteri jolly nel capitolo generico. Non è possibile utilizzare i caratteri jolly direttamente per sostituire i tipi. Fai riferimento anche a molti altri esempi forniti da varie fonti sul web. –

risposta

5

Il tutorial è terribilmente formulata. Non è possibile utilizzare un carattere jolly per nessuna delle cose elencate. È possibile utilizzare un tipo generico con un carattere jolly in esso per quelle cose.

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

Il carattere ? è il wildcard type argument.

L'articolo comincia con

Nel codice generico, il punto interrogativo (?), Chiama il jolly, rappresenta un tipo sconosciuto.

L'unico posto che è possibile utilizzare tale sintassi è come parte del codice generico, vale a dire. un argomento di tipo generico. La frase successiva si riferisce al codice generico che utilizza il carattere jolly. Così, per esempio

come il tipo di un parametro

si potrebbe avere

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

O per

come variabile locale

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

Ma

Il carattere jolly viene mai utilizzato come un argomento di tipo per un generico metodo di invocazione, una creazione di un'istanza di classe generica, o un supertipo.

Non è possibile utilizzare come

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

Vale anche la pena notare che lo stesso codice nell'ultimo snippet sarebbe valido se usasse 'T' al posto di'? 'Per la sua digitazione –

+0

In tutti quegli esempi,'? 'Non è usato come un tipo, piuttosto' Elenco 'è usato come tipo. '?' è diverso da 'Elenco '. Sono confuso: s – Solace

+1

@Solace '?' È l'argomento [tipo di carattere jolly] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1). Non può essere utilizzato al di fuori del contesto dei tipi generici. –

2

jolly può essere utilizzato con <> operatore in un concetto di farmaci generici introdotto in Java 5, usato per rappresentare tipo sconosciuto. Generics viene utilizzato per definire una classe con membro in formato generalizzato. Se si desidera fornire funzionalità che durante la creazione dell'oggetto, l'utente specificherà il tipo di membro, quindi sarà possibile utilizzare il concetto di generici. Può essere utilizzato solo per il membro dell'istanza non può essere utilizzato con il membro statico, poiché la memoria per lo statico verrà allocata solo una volta.

Il concetto jolly introdotto in generici per limitare il tipo di non conoscenza, diciamo che ho una lista che ha un carattere jolly e questa estensione jolly Number wrapper class. Ciò significa che l'elenco può funzionare con Integer, Long, Short, Byte perché estendono la classe di wrapper Number ma non con String poiché la classe String non estende la classe di wrapper Number.

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

Venendo a voi il programma, è stata utilizzata la sintassi sbagliata, come ho già detto jolly può essere utilizzato con <> operatore.

Noi non possiamo uso jolly classe, mentre un'istanza come accennato soffietto -

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

ma possiamo usare farmaci generici per fornire il campo come tipo sconosciuto come me, N, S a dipendente classe. E 'il tipo ci fornirà durante la creazione dell'oggetto della classe -

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

jolly come parametro del metodo -

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

Dichiarazione variabile locale come wildcard -

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

Possiamo usare caratteri jolly e generici come tipo di metodo di restituzione. Ecco l'esempio dei farmaci generici come tipo di ritorno di metodo -

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

Ecco l'esempio di carattere jolly come tipo di ritorno di metodo -

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

Il tuo ultimo esempio, potresti mostrare usando jolly. –

+0

aggiornato la mia risposta. – RCS

1

I caratteri jolly non hanno esistenza individuale. Vengono sempre utilizzati come parametro tipo delle classi generiche Ex: List<? extends Number>. Fornisco un esempio che copre tutti gli scenari.

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