程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 泛型中? super T和? extends T的區別,superextends

泛型中? super T和? extends T的區別,superextends

編輯:JAVA綜合教程

泛型中? super T和? extends T的區別,superextends


經常發現有List<? super T>、Set<? extends T>的聲明,是什麼意思 呢?<? super T>表示包括T在內的任何T的父類,<? extends T>表示包括T在內的任何T的子類,下面我們 詳細分析一下兩種通配符具體的區別。

 

 

extends

List<? extends Number> foo3的通配符聲明,意味著以下的賦值是合法的:

 

// Number "extends" Number (in this context) List<? extends Number> foo3 = new ArrayList<? extends Number>(); // Integer extends Number List<? extends Number> foo3 = new ArrayList<? extends Integer>(); // Double extends Number List<? extends Number> foo3 = new ArrayList<? extends Double>();

讀取操作通過以上給定的賦值語句,你一定能從foo3列表中讀取到的元素的類型是什麼呢?你可以讀取到Number,因為以上的列表要麼包含Number元素,要麼包含Number的類元素。

你不能保證讀取到Integer,因為foo3可能指向的是List<Double>。

 

你不能保證讀取到Double,因為foo3可能指向的是List<Integer>。

 

寫入操作過以上給定的賦值語句,你能把一個什麼類型的元素合法地插入到foo3中呢?

你不能插入一個Integer元素,因為foo3可能指向List<Double>。

 

你不能插入一個Double元素,因為foo3可能指向List<Integer>。

 

你不能插入一個Number元素,因為foo3可能指向List<Integer>。

 

你不能往List<? extends T>中插入任何類型的對象,因為你不能保證列表實際指向的類型是什麼,你並不能保證列表中實際存儲什麼類型的對象。唯一可以保證的是,你可以從中讀取到T或者T的子類。

 

super

現在考慮一下List<? super T>。

 

List<? super Integer> foo3的通配符聲明,意味著以下賦值是合法的:

 

// Integer is a "superclass" of Integer (in this context) List<? super Integer> foo3 = new ArrayList<Integer>(); // Number is a superclass of Integer List<? super Integer> foo3 = new ArrayList<Number>(); // Object is a superclass of Integer List<? super Integer> foo3 = new ArrayList<Object>();

讀取操作通過以上給定的賦值語句,你一定能從foo3列表中讀取到的元素的類型是什麼呢?你不能保證讀取到Integer,因為foo3可能指向List<Number>或者List<Object>。

你不能保證讀取到Number,因為foo3可能指向List<Object>。

 

唯一可以保證的是,你可以讀取到Object或者Object子類的對象(你並不知道具體的子類是什麼)。

 

寫入操作通過以上給定的賦值語句,你能把一個什麼類型的元素合法地插入到foo3中呢?你可以插入Integer對象,因為上述聲明的列表都支持Integer。

你可以插入Integer的子類的對象,因為Integer的子類同時也是Integer,原因同上。

 

你不能插入Double對象,因為foo3可能指向ArrayList<Integer>。

 

你不能插入Number對象,因為foo3可能指向ArrayList<Integer>。

 

你不能插入Object對象,因為foo3可能指向ArrayList<Integer>。

 

PECS

請記住PECS原則:生產者(Producer)使用extends,消費者(Consumer)使用super。

 

生產者使用extends

如果你需要一個列表提供T類型的元素(即你想從列表中讀取T類型的元素),你需要把這個列表聲明成<? extends T>,比如List<? extends Integer>,因此你不能往該列表中添加任何元素。

 

消費者使用super

如果需要一個列表使用T類型的元素(即你想把T類型的元素加入到列表中),你需要把這個列表聲明成<? super T>,比如List<? super Integer>,因此你不能保證從中讀取到的元素的類型。

 

即是生產者,也是消費者

如果一個列表即要生產,又要消費,你不能使用泛型通配符聲明列表,比如List<Integer>。

 

例子

請參考java.util.Collections裡的copy方法(JDK1.7):

 

 

我們可以從Java開發團隊的代碼中獲得到一些啟發,copy方法中使用到了PECS原則,實現了對參數的保護。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved