java泛型中桥方法以及协变返回类型

最近在读Core java,读到第十二章泛型部分,讲到了泛型方法的类型擦除。和泛型类型的定义一样,泛型方法在定义时自动提供了一个相应的原始类型。原始类型就是删去类型参数后的泛型类型。当类型变量被擦除后,原始类型就变为了Object。

泛型方法的类型擦除带来了一些问题,例如:

Class DateInterval extends Pair<Date>
{
    public void setSecond(Date second){
         ......
    }      
}

这个类在类型擦除后变成了这样:

class DateInterval extends Pair
{
    public void setSecond(Date second){
         .......
    }
}

但其实,还存在另外一个同名的方法

public void setSecond(Object second){
         ......
}

考虑以下调用:

DateInterval dateInterval=new DateInterval();
Pair<Date> pair=interval;
pair.setSecond(aDate);

这个时候,应该产生多态,由于pair引用了DateInterval对象,所以应该调用DateInterval的setSecond方法,但是现在有了两个同名的方法但是返回的类型不同,该调用哪一个呢?

这个时候就会产生桥方法,桥方法是一个合成方法,它看起来是这样的:

public void setSecond(Object second){
    setSecond((Date)second);
}

桥方法由编译器自动产生的,编译器创建桥方法的目的是为了保证泛型在类型擦除后还能保持继承和多态的特性。本例中pair已经声明为类型Pair<Date>,并且有一个setSecond(Object)方法,虚拟机用pair引用调用这个方法。这个对象是DateInterval类型的,因此会调用DateInterval.setSecond(Object)方法。这个方法就是合成的桥方法,它会调用DateInterval.setSecond(Date)方法,这正是我们想要的效果。

桥方法还可用在协变返回类型的情况。在早期版本的java中,子类重写父类的方法时不可以改变返回值的类型,而且必须保证方法签名相同。再后来的java版本中放宽了这一要求。即子类覆盖(即重写)基类方法时,返回的类型可以是基类方法返回类型的子类。协变返回类型允许返回更为具体的类型。要实现协变返回类型,就会产生桥方法。

posted @ 2017-05-25 14:38  原人类  阅读(562)  评论(0编辑  收藏  举报