2016-06-23 127 views
9

甲骨文doc about Wildcards in generics說,爲什麼我不能使用通配符(?)作爲參數類型,字段,局部變量或方法的返回類型?

通配符可以在多種情況下使用:作爲類型 參數字段,或局部變量的;有時候作爲返回類型 (雖然更好的編程習慣是更具體的)。

我已經在下面的類中嘗試了所有四個,並且每個都有編譯器錯誤。爲什麼?我究竟做錯了什麼?

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

因爲這是無效的語法。我沒有看到任何泛型,只是'''s。 –

+0

更好地閱讀泛型章節中通配符的子節(https://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html)。您不能直接使用通配符來替換類型。另請參閱網上各種來源提供的更多示例。 –

回答

5

教程可怕措辭。對於列出的任何內容,您都不能使用通配符。對於這些事情,您可以使用通配型及其通配符

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

?字符是wildcard type argument

本文首先

在通用代碼,問號(?),稱爲通配符, 表示一個未知的類型。

您可以使用該語法的唯一地方是作爲泛型代碼的一部分,即。泛型類型的參數。下一句是指使用通配符的通用代碼。因此,例如

作爲參數

的類型,你可以有

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

或爲

爲局部變量

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

通配符從未用作類型參數的泛型方法 調用,一個通用類實例創建或超類型。

不能使用它作爲

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

另外值得注意的是,如果使用'T'代替'?'來輸入它的最後片段中的相同代碼將是有效的 –

+0

在所有這些示例中,'?'不用作類型,而是'列表 '用作一種類型。 '?'不同於'列表'。我很困惑:s – Solace

+1

@Solace'?'是[通配符類型參數](http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1 )。它不能在泛型類型的上下文之外使用。 –

2

通配符可以與<使用>運算符在用於表示未知類型的java 5,引入泛型概念。泛型用於定義一個具有通用格式的成員的類。如果要在創建對象時提供工具,用戶將指定成員的類型,然後您可以使用泛型的概念。它只能用於實例成員不能用於靜態成員的原因,因爲靜態內存只會被分配一次。

在泛型中引入的通配符概念來限制未知類型,比方說我擁有帶有通配符的列表以及此通配符擴展Number封裝類。這意味着列表可以與Integer,Long,Short,Byte一起使用,因爲它們擴展Number包裝類,但不能與String一起作爲String類不擴展Number包裝類。

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

來到你的節目,你用錯誤的語法,正如我剛纔所說的通配符可以<>操作員使用。

我們不能使用通配符在實例類像波紋管提到 -

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

但我們可以使用泛型提供字段作爲未知類型像I,N,S的員工類。它的類型,我們將在創建類的對象提供 - 聲明局部變量作爲通配符

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

- -

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

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

通配符作爲方法的參數

我們可以使用通配符和泛型作爲方法的返回類型。 這裏是仿製藥方法的返回類型的例子 -

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

這裏是作爲方法的返回類型通配符的示例 -

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

你最後的例子,你可以使用通配符顯示。 –

+0

更新了我的答案。 – RCS

1

通配符沒有個人存在。它們總是用作泛型類型的參數類型:List<? extends Number>。我給出了一個涵蓋所有場景的例子。

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)); 
    } 
} 
相關問題