簡體   English   中英

下限通配符

[英]Lower bound wildcards

我正在嘗試了解以下代碼片段,在stackoverflow上搜索關於lowerboundupperbound的鏈接

只是想在以下幾行中克服困惑,

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> ()); 現在, DoubleInteger擴展了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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM