一個泛型類
package com.test;
import java.time.LocalDate;
public class Pair<T> {
private T fist;
private T second;
public T getFist() {
return fist;
}
public void setFist(T fist) {
this.fist = fist;
}
public T getSecond() {
return second;
}
public void setSecond(T second) {
this.second = second;
}
}
一個繼承泛型類的子類
package com.test;
import java.time.LocalDate;
public class Interval extends Pair<LocalDate> {
@Override
public void setSecond(LocalDate second){
if (second.compareTo(getFist())>=0){
super.setSecond(second);
}
}
public static void main(String[] args) {
Interval interval = new Interval();
Pair<LocalDate> pair = interval;
pair.setFist(LocalDate.now().minusDays(1));
pair.setSecond(LocalDate.now());//17行
}
}
運行字節碼
編譯器在Interval類中生成橋方法
public void setSecond(Object second){
setSecond ((LocalDate)second);
}
運行順序: 虛擬機用pari引用的對象調用 setSecond(Object)方法,即Interval.setSecond(Object) ,這個方法是編譯器自動合成的,在方法內調用Interval.setSecond(LocalDate)
橋方法的意義 用來處理類型擦除與多態之間的衝突
橋方法也用來覆蓋
public class Employee implements Cloneable{
public Employee clone() throws CloneNotSupportedException{..}
}
Employee類中將存在
Employee clone()
Object.clone() //編譯器將生產橋方法覆蓋父類Object中的clone方法,橋方法調用新定義的方法
Interval類的字節碼
// class version 52.0 (52)
// access flags 0x21
// signature Lcom/test/Pair<Ljava/time/LocalDate;>;
// declaration: com/test/Interval extends com.test.Pair<java.time.LocalDate>
public class com/test/Interval extends com/test/Pair {
// compiled from: Interval.java
// access flags 0x1
public <init>()V
L0
LINENUMBER 5 L0
ALOAD 0
INVOKESPECIAL com/test/Pair.<init> ()V
RETURN
L1
LOCALVARIABLE this Lcom/test/Interval; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1
public setSecond(Ljava/time/LocalDate;)V
L0
LINENUMBER 8 L0
ALOAD 1
ALOAD 0
INVOKEVIRTUAL com/test/Interval.getFist ()Ljava/lang/Object;
CHECKCAST java/time/chrono/ChronoLocalDate
INVOKEVIRTUAL java/time/LocalDate.compareTo (Ljava/time/chrono/ChronoLocalDate;)I
IFLT L1
L2
LINENUMBER 9 L2
ALOAD 0
ALOAD 1
INVOKESPECIAL com/test/Pair.setSecond (Ljava/lang/Object;)V
L1
LINENUMBER 11 L1
FRAME SAME
RETURN
L3
LOCALVARIABLE this Lcom/test/Interval; L0 L3 0
LOCALVARIABLE second Ljava/time/LocalDate; L0 L3 1
MAXSTACK = 2
MAXLOCALS = 2
// access flags 0x9
public static main([Ljava/lang/String;)V
L0
LINENUMBER 14 L0
NEW com/test/Interval
DUP
INVOKESPECIAL com/test/Interval.<init> ()V
ASTORE 1
L1
LINENUMBER 15 L1
ALOAD 1
ASTORE 2
L2
LINENUMBER 16 L2
ALOAD 2
INVOKESTATIC java/time/LocalDate.now ()Ljava/time/LocalDate;
LCONST_1
INVOKEVIRTUAL java/time/LocalDate.minusDays (J)Ljava/time/LocalDate;
INVOKEVIRTUAL com/test/Pair.setFist (Ljava/lang/Object;)V
L3
LINENUMBER 17 L3
ALOAD 2
INVOKESTATIC java/time/LocalDate.now ()Ljava/time/LocalDate;
INVOKEVIRTUAL com/test/Pair.setSecond (Ljava/lang/Object;)V
L4
LINENUMBER 18 L4
RETURN
L5
LOCALVARIABLE args [Ljava/lang/String; L0 L5 0
LOCALVARIABLE interval Lcom/test/Interval; L1 L5 1
LOCALVARIABLE pair Lcom/test/Pair; L2 L5 2
// signature Lcom/test/Pair<Ljava/time/LocalDate;>;
// declaration: pair extends com.test.Pair<java.time.LocalDate>
MAXSTACK = 4
MAXLOCALS = 3
// access flags 0x1041
public synthetic bridge setSecond(Ljava/lang/Object;)V
L0
LINENUMBER 5 L0
ALOAD 0
ALOAD 1
CHECKCAST java/time/LocalDate
INVOKEVIRTUAL com/test/Interval.setSecond (Ljava/time/LocalDate;)V
RETURN
L1
LOCALVARIABLE this Lcom/test/Interval; L0 L1 0
MAXSTACK = 2
MAXLOCALS = 2
}