2014-10-08 176 views
5

使用通配符我宣佈下面給出其參數是Number型的方法:在方法參數

public static void organizeData(java.util.List<? extends Number> c) { 
    //operation on the list 
} 

我能夠通過任何非參數列表作爲參數。那麼使用通配符<? extends Number>有什麼意義?

List newList = new LinkedList<>(); 
ClassName.organizeData(newList); 

爲什麼我從c得到Object類型的元素?而不是類型Number?有沒有辦法只允許一個類型的子類型作爲參數傳遞,而不是允許非參數化的參數呢?

+5

你不能阻止。用戶總是可以首先投射到原始類型,然後投射到任何需要的地方。泛型有其侷限性,原始類型總是打破它們。 – 2014-10-08 13:35:13

回答

6

你在這裏問三個問題,我會單獨回答。順便問一下,你會發現非常值得閱讀Java Generics FAQ - considered by many to be the canonical reference on the subject

  1. 那麼,什麼是使用通配符<? extends Number>點?

您需要使用通配符的時候,參數化的參數是Number,比方說,Integer一個子類。例如:

import java.util.LinkedList; 
import java.util.List; 

public class NumberTest { 
    public static void main(String... args) { 
     List<Integer> newList = new LinkedList<Integer>(); 
     organizeData(newList); // This works! 
     anotherMethod(newList); // Doesn't compile 
    } 

    private static void organizeData(List<? extends Number> list) { 

    } 

    private static void anotherMethod(List<Number> list) { 

    } 
} 

第二種方法調用失敗,編譯錯誤:

NumberTest.java:9: error: method anotherMethod in class NumberTest cannot be applied to given types; 
         anotherMethod(newList); // Doesn't compile 
         ^
    required: List<Number> 
    found: List<Integer> 
    reason: actual argument List<Integer> cannot be converted to List<Number> by method invocation conversion 
1 error 

  • 爲何我從c得到Object型的元件?而不是類型Number
  • 您在第二種情況下得到一個類型的Object的原因是因爲you are using the Raw Type.你不應該使用原始類型,如果你能避免它出於這個原因 - 你失去編譯器的類型檢查的所有優點。


  • 有一種方法以允許相對於允許非參數化的參數也僅一個類型的子類型作爲參數傳遞?
  • 您不能防止Heap Pollution在你的描述,因爲有人可以隨時轉換爲原始類型,然後到任何需要的方式。泛型只是一個編譯時構造,並且are ultimately erased after compilation.這就是爲什麼未檢查類型轉換警告只能通過註釋來抑制。

    1

    您必須記住,在Java中,泛型是編譯時構造以幫助實現類型安全。在運行時,類型擦除將所有通用類型轉換爲Object,並在需要時添加鑄件。如果繞過使用原始類型(編譯器給出警告)的編譯時檢查,則繞過了泛型的好處(編譯時類型檢查和運行時安全轉換)。

    0

    Java中的泛型通過類型擦除來實現。一世。e:在運行時不存在您在<>中指定的類型信息。在編譯期間,java編譯器利用<>中給出的信息來確保所有內容都按順序排列。但是,如果您沒有在變量'newList'中指定<>中的類型,則不會阻止將它傳遞給'organizationalData'方法。