加载中...

泛型的多态


前言

最近在复习泛型时,看到一个关于泛型的多态的知识点。感觉挺有意思的,在这里记录一下。

问题引入

我们都知道,泛型是作用于编译期,是为了在编译期保证类型约束与提供类型安全型的,在编译过程泛型会被擦除,运行期不会得到对应的泛型信息。对于无限制的泛型参数,擦除后会被直接替换成Object;对于有限制的泛型参数,会被替换成上下界上界,比如<T extends Number><? extends Number>会被替换成上界Number,<? super Number>会被替换成上界Object。

问题就从这里来了,泛型擦除会导致多态出现问题。比如有一个这样的父类和其子类:

public class Message<T> {
    public T get(T var){
        return var;
    }
}
class SmsMessage extends Message<Integer> {
    @Override
    public Integer get(Integer var) {
        return var;
    }
}

经过泛型擦除之后,按照理论来说将会得到下面这样的结果:

public class Message<Object> {
    public Object get(Object var){
        return var;
    } 
}
public class SmsMessage extends Message<Integer> {
    @Override
    public Integer get(Integer var) {
        return var;
    }
}

可以看到,父类和其子类定义的参数和返回值将会不一样,这样两者就不是Override(重写)的关系了,而应该是Overload(重载)关系。

而多态的定义是:同一个行为具有多个不同表现形式或形态的能力,多态有三个的必要条件:

1、要有继承

2、要有override(重写)

3、父类引用指向子类对象

可见如果不能实现重写将会导致多态不能实现。

解决办法

JVM采用了一个叫做桥接的特殊方法解决类型擦除和多态的冲突问题。

通过javap命令对编译后的SmsMessage.class文件进行反编译,得到下面的反编译后的结果:

class SmsMessage extends Message<java.lang.Integer> {
  SmsMessage();
  public java.lang.Integer get(java.lang.Integer);   
  public java.lang.Object get(java.lang.Object);     
}

可以看到,编译后的类中其实存在两个get方法,分别对应于上文所说的父类、子类的get方法,而第二个get方法其实就是所谓的桥接方法。我们进一步用javap -c反编译得到字节码:

class SmsMessage extends Message<java.lang.Integer> {
  SmsMessage();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method Message."<init>":()V
       4: return

  public java.lang.Integer get(java.lang.Integer);
    Code:
       0: aload_1
       1: areturn

  public java.lang.Object get(java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: checkcast     #7                  // class java/lang/Integer
       5: invokevirtual #9                  // Method get:(Ljava/lang/Integer;)Ljava/lang/Integer;
       8: areturn
}

可以看到,在第二个get方法的5: invokevirtual #9处,调用了第一个get方法,这个桥接方法就搭建起了父类和子类间的桥梁,使得多态与泛型擦除不会存在冲突问题了。


文章作者: DestiNation
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 DestiNation !
  目录