Java基礎之泛型程序設計

泛型程序設計
簡要介紹

    類型變量使用大寫形式,且比較短,在Java庫中,使用變量E表示集合的元素類型,K和V分別表示表的關鍵字與值得類型。Object 表示”任意類型”
    程序清單使用了Pair類,靜態(tài)的minmax方法遍歷了數(shù)組并同時計算出最大值和最小值。它用一個Pair對象返回了兩個結果。
    compareTo 方法只有 Comparable 接口有該方法,所以我們要將T限制為實現(xiàn)了Comparable接口的
    的類

類型擦除

無論何時定義一個泛型類型,都自動提供了一個相應的原始類型,原始類型的名字就是刪去參數(shù)后的泛型類型名,擦除類型變量,并替換為限定類型(無限定的變量用Object)
例如:Pair 的原始類型如下所示:

public class Pair <Object>{
    private Object name;
    private Object bonus;

    public Object getFirst() {
        return name;
    }

    public void setFirst(Object name) {
        this.name = name;
    }

    public Object getSecond() {
        return bonus;
    }

    public void setSecond(Object bonus) {
        this.bonus = bonus;
    }

    public Pair(){}
    public Pair(Object name, Object bonus) {
        this.name = name;
        this.bonus = bonus;
    }

    @Override
    public String toString() {
        return "Pair{" +
                "name=" + name +
                ", bonus=" + bonus +
                '}';
    }


類型擦除帶來的方法參數(shù)不統(tǒng)一,編譯器通過橋方法來處理。
與Java泛型轉(zhuǎn)換的事實

    虛擬機中沒有泛型,只有普通的類和方法。
    所有的類型參數(shù)都用它們的限定類型替換
    橋方法被合成來保持多態(tài)
    為保持類型安全性,必要時插入強制類型轉(zhuǎn)換。

約束與局限性

    不能用基本類型實例化類型參數(shù)

例如沒有 Pair<double>,只有 Pair<Double>

    運行時類型查詢只適用于原始類型
    例如:

Pair<String> stringPair=new Pair<String>();
Pair<Employee> employeePair=new Pair<Employee>();
if(stringPair.getClass()==employeePair.getClass())

 
其比較結果是true,這是因為兩次調(diào)用getClass都將返回 Pair.class

    不能創(chuàng)建參數(shù)化類型的數(shù)組
    例如:
    Pair<String>[] table=new Pair<String>[10] //error

    Varargs 警告

public static <T> void addAll(Collection<T> coll,T ... ts){
    for(t: ts) coll.add(t);
}


現(xiàn)考慮以下調(diào)用:


Collection<Pair<String>> table=...;
Pair<String> pair1=...;
Pair<String> pair2=...;
Pair<String> pair3=...;
addAll(table,pair1,pair2);


為了調(diào)用這個方法,Java虛擬機必須建立一個Pair 數(shù)組。這就違反了前面的規(guī)則。
不過,對于這種情況,規(guī)則有所放松,你只會得到一個警告,而不是錯誤。

可以采取兩種方法來抑制這個警告。一種方法是為包含addAll調(diào)用的方法增加注解@SuppressWarnings(“unchecked”)?;蛘咴贘ava SE 7中,還
可以用@SafeVarargs直接標注addAll方法。

5 不能實例化類型變量
不能使用像new T(…),new T[…] 或T.class 這樣的表達式中的類型變量,例如下面
Pair 構造器就是非法的:
public Pair(){name=new T();bonus=new T();}
類型擦除將T改變成了Object,而且,其本意肯定不希望調(diào)用new Object()。在Java SE 8之后,最好的解決辦法是讓調(diào)用者
提供一個構造器表達式。例如:
Pair<String> p=Pair.makePair(String::new)
6. 不能構造泛型數(shù)組
例如:
public static <T extends Comparable> T[] minmax(T[] a){T[] mm=new T[2];} //error
7. 泛型類的靜態(tài)上下文中類型變量無效
不能再靜態(tài)域或方法中引用類型變量。例如:
“`
public class Signleton {
private static T signleStance; //Error
public static T getSignleStance(){ //True
if(signleStance==null){
return signleStance;
}
}
}

8. 不能拋出或者捕獲泛型類的實例

既不能拋出也不能捕獲泛型類對象。實際上,甚至泛型類擴展Throwable都是不合法的。
例如:以下定義就不能正常編譯:
`public class Problem<T> extends Exception{}`

9. 可以通過 `@SuppressWarnings('unchecked')` 來消除對受查異常的檢查。
### 泛型類型的繼承規(guī)則
1. 通配符的使用

public static void main(String[] args) {
Pair managerPair = new Pair<>();
printBuddies(managerPair);

}

public static void printBuddies(Pair<? extends  Employee> employeePair) {
    Employee name = employeePair.getFirst();
    Employee bonus = employeePair.getSecond();
    System.out.println("name:"+name+"bonus:"+bonus);
}


這種情況會編譯報錯



//Test 2
Pair

下面是泛型的綜合應用:


package com.jay.generic;

import com.jay.generic.employee.Employee;
import com.jay.generic.employee.Manager;

/**
* 泛型綜合總結應用
* Created by xiang.wei on 2018/1/21
*
* @author xiang.wei
*/
public class PairTest3 {
public static void main(String[] args) {
Manager ceo = new Manager(“xiang”, 10000);
Manager cfo = new Manager(“l(fā)i”, 8000);
Pair managerPair = new Pair<>(ceo, cfo);
printBuddies(managerPair);

    ceo.setBonus(2000);
    cfo.setBonus(1000);

    Manager[] managers = {ceo, cfo};
    minmaxBonus(managers, managerPair);
    System.out.println("first:"+managerPair.getFirst().getName()+",second:"+managerPair.getSecond().getName());
    maxminBonux(managers,managerPair);
    System.out.println("first:"+managerPair.getFirst().getName()+",second:"+managerPair.getSecond().getName());

}


public static void printBuddies(Pair<? extends Employee> pair) {
    Employee first = pair.getFirst();
    Employee second = pair.getSecond();
    System.out.println("first="+first.getName()+"------second="+second.getName());
}

public static void minmaxBonus(Manager[] managers, Pair<? super Manager> result) {
    if (managers.length == 0) {
        return;
    }
    Manager min = managers[0];
    Manager max = managers[0];
    for (int i = 0; i < managers.length; i++) {
        if (min.getBonus() > managers[i].getBonus()) {
            min = managers[i];
        }
        if (max.getBonus() < managers[i].getBonus()) {
            max = managers[i];
        }
    }
    result.setFirst(min);
    result.setSecond(max);
}

public static void maxminBonux(Manager[] managers, Pair<? super Manager> result) {
    if (managers.length == 0) {
        return;
    }
    minmaxBonus(managers, result);
    PairAlg.swapHelper(result);
}



}

/**
*
*/
class PairAlg {
/**
* @param pair
* @return
*/
public static boolean hasNulls(Pair




作者:碼農(nóng)飛哥
微信公眾號:碼農(nóng)飛哥