首页 » 编写高质量代码:改善Java程序的151个建议 » 编写高质量代码:改善Java程序的151个建议全文在线阅读

《编写高质量代码:改善Java程序的151个建议》建议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),而且让“泛型”很汗颜:已经使用泛型限定参数的边界了,还要进行泛型类型判断。事实上,使用多重边界可以很方便地解决问题,而且非常优雅,建议读者在开发中考虑使用多重限定。