java泛型之有界类型

在前面的例子中,可以使用任意类替换类型参数。对于大多数情况这很好,但是限制能够传递给类型参数的类型有时是有用的。例如,假设希望创建一个类,而且这个类中包含一个返回数组中数字平均值的方法。希望该方法可以计算任意类型数字的平均值,包含整形、单精度浮点型以及双精度浮点型。因此,希望使用类型参数以泛型化的方式指定数字类型。见示例:

package test;

public class Stats<T> {

    private T[] nums;
    
    public Stats(T[] o) {
        nums = o;
    }
    public double average() {
        double sum = 0d;
        for(int i = 0; i < nums.length; i++)
            sum += nums[i].doubleValue();        //这里是错误的
        return sum /nums.length;
    }
}

在Stats类中,average()方法通过调用doubleValue(),试图获得nums数组中每个数字的double版本,因为所有数值类,比如Integer以及Double,都是Number的子类,而Number定义了doubleValue()方法,所以所有数值类型的封装器都可以使用该方法。问题是编译器不知道你正试图创建只使用数值类型的Stats对象因此,当试图编译Stats时,会报错误,指出doubleValue()方法是未知的。为了解决这个问题,需要以某种方式告诉编译器,你打算只向T传递数值类型。此外,需要以某种方式确保实际上只传递了数值类型。

为了处理这种情况,java提供了有界类型(dounded type)。在指定类型参数时,可以创建声明超类的上界注:在声明时,这里只有上界,也就是使用extends,没有下界,也就是不能使用super泛型中什么时候会使用super关键字,我们后面会讲到!),所有类型参数都必须派生自超类。这是当指定类型参数时使用extends子句完成的,如下所示:

<T extends superclass>

这样就指定T只能被superclass其子类替代。因此,superclass定义了包括superclass在内的上限。针对上例,我们可以通过将Number指定为上界,修复前面显示的Stats类,示例如下:

package test;

public class Stats<T extends Number> {

    private T[] nums;
    
    public Stats(T[] o) {
        nums = o;
    }
    public double average() {
        double sum = 0d;
        for(int i = 0; i < nums.length; i++)
            sum += nums[i].doubleValue();    
        return sum /nums.length;
    }
}

package test;

public class BoundsDemo {
    public static void main(String[] args) {
        Integer inums[] = {1,2,3,4,5};
        Stats<Integer> iob = new Stats<>(inums);
        double v = iob.average();
        System.out.println("iob average is " + v);
        Double dnums[] = {1.1,2.2,3.3,4.4,5.5};
        Stats<Double> dob = new Stats<>(dnums);
        double w = dob.average();
        System.out.println("dob average is " + w);
    }
}

注意现在使用下面这行代码声明Stats的方式:

public class Stats<T extends Number> {......}

现在使用Number对类型T进行了限定,java编译器知道所有T类型的对象都可以调用doubleValue()方法,因为该方法是由Number声明的。

除了使用类作为边界之外,也可以使用接口。实际上,可以指定多个接口作为边界。此外,边界可以包含一个类和一个或多个接口。对于这种情况,必须首先指定类类型,也就是把类类型放在extends之后的第一个位置如果边界包含接口类型,那么只有实现了那种接口的类型参数是合法的。当指定具有一个类和一个或多个接口的边界时,使用&运算符连接它们。如下:

class Gen<T extends MyClass & MyInterface> {......}

在此,通过类MyClass和接口MyInterface对T进行限制。因此,所有传递给T的类型参数都必须是MyClass的子类,并且必须实现MyInterface接口。

转载于:https://my.oschina.net/fhd/blog/290122

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值