java 泛型--桥方法

因为 java 在编译源码时, 会进行 类型擦除, 导致泛型类型被替换限定类型(无限定类型就使用 Object). 因此为保持继承和重载的多态特性, 编译器会生成 桥方法.

本文最后附录所有源码.

Pair 是个泛型类, 它具有泛型方法 setSecond(T second),
在经过编译时的 类型擦除 后变为 setSecond(Object second).

DateInterval 是 Pair<LocalDate> 的实例化子类, 它具有方法 setSecond(LocalDate second).

在 Main.main 中, 我们新建 DateInterval 对象, 并用基类 Pair<LocalDate> 来引用它,
此时调用基类的 setSecond 方法时, 我们希望它能够实现多态, 即调用 DateInterval.setSecond(LocalDate) 方法.
事实上, java 编译器通过插入 桥方法 的方式, 帮助我们实现了该功能.

反编译 DateInterval.class 会发现它具有两个 setSecond 方法:

  1. void setSecond(LocalDate);
  2. void setSecond(Object).

并且, 在 void setSecond(Object) 中会调用 void setSecond(LocalDate), 这就是所谓的桥方法.

附: DateInterval.class 反编译后的代码:

Compiled from "DateInterval.java"
public class com.book.chapter8.DateInterval extends com.book.chapter8.Pair<java.time.LocalDate> {
  public com.book.chapter8.DateInterval();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method com/book/chapter8/Pair."<init>":()V
       4: return

  public void setSecond(java.time.LocalDate);
    Code:
       0: aload_1
       1: aload_0
       2: invokevirtual #2                  // Method getFirst:()Ljava/lang/Object;
       5: checkcast     #3                  // class java/time/chrono/ChronoLocalDate
       8: invokevirtual #4                  // Method java/time/LocalDate.compareTo:(Ljava/time/chrono/ChronoLocalDate;)I
      11: iflt          19
      14: aload_0
      15: aload_1
      16: invokespecial #5                  // Method com/book/chapter8/Pair.setSecond:(Ljava/lang/Object;)V
      19: return

  public void setSecond(java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: checkcast     #6                  // class java/time/LocalDate
       5: invokevirtual #7                  // Method setSecond:(Ljava/time/LocalDate;)V
       8: return
}

附: 其他所有源码:

Pair.java:

package com.book.chapter8;

/**
 * Created by zhixiao.mzx on 2016/11/5.
 */
public class Pair<T> {
    private T first;
    private T second;

    public Pair() {
        first = null;
        second = null;
    }

    public Pair(T first, T second) {
        this.first = first;
        this.second = second;
    }

    public T getFirst() {
        return first;
    }

    public void setFirst(T first) {
        this.first = first;
    }

    public T getSecond() {
        return second;
    }

    public void setSecond(T second) {
        this.second = second;
    }
}

DateInterval.java:

package com.book.chapter8;

import java.time.LocalDate;

/**
 * Created by zhixiao.mzx on 2016/11/5.
 */
public class DateInterval extends Pair<LocalDate> {
    public void setSecond(LocalDate second) {
        if (second.compareTo(getFirst()) >= 0) {
            super.setSecond(second);
        }
    }
}

Main.java:

package com.book.chapter8;

import java.time.LocalDate;

/**
 * Created by zhixiao.mzx on 2016/11/5.
 */
public class Main {
    public static void main(String[] args) {
        DateInterval interval = new DateInterval();
        Pair<LocalDate> pair = interval;
        pair.setFirst(LocalDate.now());
        pair.setSecond(LocalDate.now());
    }
}
 
分类: java
posted @ 2017-08-08 19:09  穆穆兔兔  阅读(531)  评论(0编辑  收藏  举报