本文講述以下幾個方面的內容試圖說明泛型類型的子類及通配符的使用
() 子類及替換原則
() 使用extends關鍵字的通配符
() 使用super關鍵字的通配符
() 子類及替換原則
在java語言中我們通俗講一個類是另一個類的子類型是通過使用extends關鍵字去繼承某一個類或者使用implements關鍵字去實現某些接口這樣我們在編程時就可以面向接口或基類進行編程如
Number num = new Integer()
Number num = new Double(d)
這個就是所謂的替換原則替換原則的定義是
Substitution Principle a variable of a given type may be assigned a value of any subtype of that type and a method with a parameter of a given type may be invoked with an argument of any subtype of that type
大概的意思是說某種類型的變量可以被該類型的任何子類所賦值一個方法中的參數也可以被該參數的任何子類進行調用
現在我們再來看看泛型中替換原則的適用性
Example
List<Number> listNums = new ArrayList<Number>()
numsadd()
numsadd()
在example 中可以看出替換原則被很好地應用在這裡ArrayList是List的子類我們提供給listNums變量的類型參數為Number往 listNums中添加元素時被封箱為Integer類型而Integer是Number的子類第三行的情況類似
Example
List<Integer> intList = new ArrayList<Integer>()
List<Number> numList = intList //compile error
…
numListadd() // cant do that
根據替換原則我們會很容易想到既然Integer是Number的子類則我們應該可以將List<Integer>的變量賦給 List<Number>的變量但從實際情況表明List<Integer>並不是List<Number>的子類
我們不妨試想想若果List<Integer>類型的變量可以成功賦值給List<Number>類型的變量會出現什麼情況?我們可能在程序的某個位置添加一個double類型的元素進去numList中而實質上在numList中其它元素都是Integer 的類型的元素這樣就違背了泛型的初衷了
有時我們確實希望將形如List<Integer>的List對象賦給List<Number>的變量這時就要使用extends關鍵字的通配符
() 使用extends關鍵字的通配符
Example
List<Integer> intList = new ArrayList<Integer>()
List<? extends Number> numList = intList()
…
numListadd() //compile error (cant do that)
從Example看到numList這個變量我們可以將類型參數為Number及其Number子類的List賦給它
記住一條規則如果你使用了? extends T一般情況下你不能往該數據結構中put元素而你可以做的就是get元素
如果要往內put元素就需要使用下面提到的super關鍵字的通配符
() 使用super關鍵字的通配符
Example
List<Integer> intList = new ArrayList<Integer()
List<? super Integer> numList = intList
numListadd() //can put integer or null
在example 我們可以看到<? super Integer>的意思為我們可以將類型參數為Integer或Integer超類的List賦給 numList變量並且可以put元素到列表中(注意在該例子中put進的元素只能為Integer或null類型)
一條比較通用的規則如果要往List中put元素則用<? super T>如果要從List中get元素則用<? extends T>如果既要get又要put則不使用通配符
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26223.html