讀古今文學網 > 編寫高質量代碼:改善Java程序的151個建議 > 建議99:嚴格限定泛型類型採用多重界限 >

建議99:嚴格限定泛型類型採用多重界限

從哲學上來說,很難描述一個具體的人,你可以描述它的長相、性格、工作等,但是人都是有多重身份的,估計只有使用多個And(與操作)將所有的描述串聯起來才能描述一個完整的人,比如我,上班時我是一個職員,下班了坐公交車我是一個乘客,回家了我是父母的孩子,是兒子的父親……角色時刻在變換。那如果我們要使用Java程序來對一類人進行管理,該如何做呢?比如在公交車費優惠系統中,對部分人員(如工資低於2500元的上班族並且是站立著的乘客)車費打8折,該如何實現呢?

注意這裡的類型參數有兩個限制條件:一為上班族;二為是乘客。具體到我們的程序中就應該是一個泛型參數具有兩個上界(Upper Bound),首先定義兩個接口及實現類,代碼如下:


//職員

interface Staff{

//工資

public int getSalary();

}

//乘客

interface Passenger{

//是否是站立狀態

public boolean isStanding();

}

//定義「我」這個類型的人

class Me implements Staff, Passenger{

public boolean isStanding(){

return true;

}

public int getSalary(){

return 2000;

}

}


"Me"這種類型的人物有很多,比如做系統分析師也是一個職員,也坐公交車,但他的工資實現就和我不同,再比如Boss級的人物,偶爾也坐公交車,對大老闆來說他也只是一個職員,他的實現類也不同,也就是說如果我們使用"T extends Me"是限定不了需求對象的,那該怎麼辦呢?可以考慮使用多重限定,代碼如下:


//工資低於2500元的上班族並且站立的乘客車票打8折

public static<T extends Staff&Passenger>void discount(T t){

if(t.getSalary()<2500&&t.isStanding()){

System.out.println("恭喜你!您的車票打八折!");

}

}

public static void main(Stringargs){

discount(new Me());

}


使用「&」符號設定多重邊界(Multi Bounds),指定泛型類型T必須是Staff和Passenger的共有子類型,此時變量t就具有了所有限定的方法和屬性,要再進行判斷就易如反掌了。

在Java的泛型中,可以使用「&」符號關聯多個上界並實現多個邊界限定,而且只有上界才有此限定,下界沒有多重限定的情況。想想你就會明白:多個下界,編碼者可自行推斷出具體的類型,比如"?super Integer"和"?extends Double",可以更細化為Number類型了,或者Object類型了,無須編譯器推斷了。

為什麼要說明多重邊界?是因為編碼者太少使用它了,比如一個判斷用戶權限的方法,使用的是策略模式(Strategy Pattern),示意代碼如下:


public class UserHandler<T extends User>{

//判斷用戶是否有權限執行操作

public boolean permit(T user, List<Job>jobs){

List<Class<?>>iList=Arrays.asList(user.getClass().getInterfaces());

//判斷是否是管理員

if(iList.indexOf(Admin.class)>-1){

Admin admin=(Admin)user;

/*判斷管理員是否有此權限*/

}else{

/*判斷普通用戶是否有此權限*/

}

return false;

}

}


此處進行了一次泛型參數類別判斷,這裡不僅僅違背了單一職責原則(Single Responsibility Principle),而且讓「泛型」很汗顏:已經使用泛型限定參數的邊界了,還要進行泛型類型判斷。事實上,使用多重邊界可以很方便地解決問題,而且非常優雅,建議讀者在開發中考慮使用多重限定。