[英]Lower bound wildcards
我正在嘗試了解以下代碼片段,在stackoverflow上搜索關於lowerbound和upperbound的鏈接
只是想在以下幾行中克服困惑,
si = s //好嗎? 對象數組可以隱式地轉換為整數數組?
List<? extends Number> l = new ArrayList<>();
List<? extends Integer> i = new ArrayList<>();
l = i;//OK i is a subtype of l
List<? super Number> s = new ArrayList<>();
List<? super Integer> si = new ArrayList<>();
si = new ArrayList<Integer>();//OK understand integer matches the pattern of ? super Integer
s = new ArrayList<Object>();//OK understand that object is superclass of Number
si=s//OK why? arrays of objects can be implicitly casted to arrays of integers?
//consider this
List<Integer> integers = new ArrayList<Integer>();
List<Object> objects = new ArrayList<Object>();
integers = objects; //NOT OK Type mismatch: cannot convert from List<Object> to List<Integer>
//consider this
Integer ten = 10; //integer ten
Object none = new Object();//some none
ten = none;//NOT OK none cannot be implicitly casted to ten
任何幫助表示贊賞
請記住,gnerics是為了編譯器而不是運行時信息。
當你執行si = s
你將一個屬於Number的超類的List分配給一個變量,該變量可以引用一個Integer超類的List。
如果它是Number的列表,它仍然是Something的一個列表,它是Integer的超類。
我們知道它實際上是一個對象的Arraylist,因為你之前已經分配過。
我們也知道Object的ArrayList擴展了Object的List。
對象列表是一個超類數的列表,這就是前一個賦值的工作原因。
我們也知道List of Object是一個Integer超類的列表,但它與編譯器無關,它只關心Number的任何超類也是Integer的超類。
我想知道你是否清楚為什么要使用<? super Number>
<? super Number>
而不是<? extends Number>
<? extends Number>
...
聲明一個帶<? extends Number>
的類型 <? extends Number>
guarantee <? extends Number>
到任何采用該類型的東西,它至少會尊重Number
的合約。 但是給出這種類型列表的一段代碼不能將新成員添加到列表中。 考慮以下代碼:
void appendInteger (List <? extends Number> list) {
list.add (new Integer (3)); // Compiler error on this line
}
你可以用appendInteger (new ArrayList <Double> ());
調用它appendInteger (new ArrayList <Double> ());
現在, Double
和Integer
擴展了Number
,因此編譯后將接受該參數。 但是你可以看到,如果允許附加,那么違反調用代碼中聲明的合同。 因此,編譯器不允許任何代碼添加或替換使用<? extends T>
聲明的任何結構中的成員<? extends T>
<? extends T>
。 上述方法將導致編譯器錯誤。
簡而言之,對於上限的通配符類型,您可以讀取項目,但不能將成員放入結構中。
相反,使用List <? super Number>
List <? super Number>
表示列表中的對象不比Number
更具體 。 考慮這種方法:
void getInteger (java.util.List <? extends Number> list) {
Number n = list.get (0); // Compiler error on this line
}
代碼不知道list
元素的類型。 所以編譯器也會用這個方法嘔吐。 您可以使用Number
的繼承路徑中的任何類型的對象在list
添加或替換成員。 但要讀取列表成員,您必須將它們視為Object
類型或使用類型轉換:
Object v = list.get (0); // this will work
Number n = (Number) list.get (0); // this will also work
有了這些知識,再看一下si = s
涉及的對象。 請記住,您無法從這些結構中讀取項目,只能添加或替換成員。 您可以放置在s
任何對象也可以在si
接受。 因此,將s
分配給si
是可以接受的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.