淺談Java泛型

概述

Java泛型是J2SE1.5中引入的一個新特性,其本質是參數化類型,也就是說所操做的數據類型被指定爲一個參數(type parameter)這種參數類型能夠用在類、接口和方法的建立中,分別稱爲泛型類、泛型接口、泛型方法。數據結構

有關泛型的基礎知識這裏就不說了,咱們直接來看看Java泛型的高階用法。函數

extends

定義

有時候,你會但願泛型類型只能是某一部分類型,其實就是給泛型參數添加一個界限。其定義形式爲:
<T extends BoundingType>
必定要很是注意的是,這裏的extends不是類繼承裏的那個extends!兩個根本沒有任何關聯。
在這裏extends後的BoundingType能夠是類,也能夠是接口,意思是說,T是在BoundingType基礎上建立的,具備BoundingType的功能。.net

綁定接口/類

public interface Comparable<T> {
    public boolean compareTo(T i);
}
//添加上extends Comparable以後,就能夠Comparable裏的函數了
public static <T extends Comparable>  T min(T...a){
    T smallest = a[0];
    for(T item:a){
        if (smallest.compareTo(item)){
            smallest = item;
        }
    }
    return smallest;
}

從這段代碼也能夠看出,類型綁定有兩個做用:
一、對填充的泛型加以限定
二、使用泛型變量T時,可使用BoundingType內部的函數。3d

通配符

無邊界通配符:?

Point point; 
point = new Point(3,3); 
point = new Point(4.3f,4.3f);
point = new Point(4.3d,4.90d); 
point = new Point(12l,23l);

各類類型的Point實例,均可以賦值給point了。
這裏的?就是無邊界通配符。它是一個未知的符號,能夠是表明任意的類。code

通配符?的extends綁定

咱們給通配符加上限定: Point<? extends Number> point;
這裏雖然是指派生自Number的任意類型,但你們注意到了沒: new Point<Number>()也是能夠成功賦值的,這說明包括邊界自身。對象

注意:利用<? extends Number>定義的變量,只可取其中的值,不可修改。看下面代碼:blog

Point<? extends Number> point;
point=new Point<Integer>(3,33);
Number integer_1=point.getX();//編譯成功
point.setX(new Integer(222));//編譯錯誤

明顯在point.setX(new Integer(122))時報編譯錯誤。但point.getX()卻不報錯。
這是爲何呢?
首先,point的類型是由Point<? extends Number>決定的,並不會由於point = new Point<Integer>(3,3)而改變類型。
正由於point的類型爲 Point<? extends Number> point,那也就是說,填充Point的泛型變量T的爲<? extends Number>,這是一個什麼類型?未知類型!!!怎麼可能能用一個未知類型來設置內部值!這徹底是不合理的。
但取值時,正因爲泛型變量T被填充爲<? extends Number>,因此編譯器能肯定的是Number確定是<? extends Number>的父類,因此不報錯。
也就是說,編譯器,只要能肯定通配符類型,就會容許,若是沒法肯定通配符的類型,就會報錯。繼承

通配符?的super綁定

若是說 <? extends XXX>指填充爲派生於XXX的任意子類的話,那麼<? super XXX>則表示填充爲任意XXX的父類!接口

class Employee {}
class Manager extends Employee {}
class CEO extends Manager {}

List<? super Manager> list;
list = new ArrayList<Employee>();
list.add(new Employee()); //編譯錯誤
list.add(new Manager());//編譯成功
list.add(new CEO());//編譯成功

編譯器沒法肯定<? super Manager>的具體類型,但惟一能夠肯定的是Manager、CEO確定是<? super Manager>的子類,因此確定是能夠add進去的。
但Employee不必定是<? super Manager>的子類,因此不能肯定,不能肯定的,確定是不容許的,因此會報編譯錯誤。get

總結 ? extends 和 ? super 通配符的特徵,咱們能夠得出如下結論:
◆ 若是你想從一個數據類型裏獲取數據,使用 ? extends 通配符(能取不能存)
◆ 若是你想把對象寫入一個數據結構裏,使用 ? super 通配符(能存不能取)
◆ 若是你既想存,又想取,那就別用通配符。

參考:Java泛型

相關文章
相關標籤/搜索