Java 语法糖 - 方法重写时的桥接方法
Java About 3,711 words桥接方法
子类重写的方法的返回值可以是父类方法的返回值的子类。
本质
编译器帮忙生成了合成的桥接方法。
内部有一个重写父类相同返回值的方法,以及子类重写的返回值类型的方法。
Java 代码
子类B
的method
方法的返回值是Integer
类型是父类A
的method
方法返回值Number
类型的子类。
class A {
public Number method() {
return 1;
}
}
class B extends A {
@Override
public Integer method() { // Integer 是 Number 的子类
return 2;
}
}
编译后
通过IDEA
中的View
-Show Bytecode
可参看字节码(带了synthetic
、bridge
关键字)。
(此处的方法是根据反编译后的字节码推得的伪代码)
class B extends A {
public Integer method() {
return 2;
}
// 真正重写父类的 Number 方法
public synthetic bridge Number method() {
return method(); // 调用自身的 method 方法
}
}
代码验证
可以看到getDeclaredMethods
方法获得的两个方法。
public class Test9 {
public static void main(String[] args) throws NoSuchMethodException {
Method[] methods = B.class.getDeclaredMethods();
for (Method m : methods) {
System.out.println("method name#" + m.getName() + ", returnType#" + m.getReturnType() + ", isSynthetic#" + m.isSynthetic() + ", isBridge#" + m.isBridge() + ", method#" + m);
}
}
}
输出
method name#method, returnType#class java.lang.Integer, isSynthetic#false, isBridge#false, method#public java.lang.Integer com.example.B.method()
method name#method, returnType#class java.lang.Number, isSynthetic#true, isBridge#true, method#public java.lang.Number com.example.B.method()
IDEA 生成的字节码
可以看到IDEA
直接帮忙生成了可读性更好的public synthetic bridge method()
方法。
// class version 52.0 (52)
// access flags 0x20
class com/example/B extends com/example/A {
// compiled from: B.java
// access flags 0x0
<init>()V
L0
LINENUMBER 3 L0
ALOAD 0
INVOKESPECIAL com/example/A.<init> ()V
RETURN
L1
LOCALVARIABLE this Lcom/example/B; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1
public method()Ljava/lang/Integer;
L0
LINENUMBER 6 L0
ICONST_2
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
ARETURN
L1
LOCALVARIABLE this Lcom/example/B; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1041
public synthetic bridge method()Ljava/lang/Number;
L0
LINENUMBER 3 L0
ALOAD 0
INVOKEVIRTUAL com/example/B.method ()Ljava/lang/Integer;
ARETURN
L1
LOCALVARIABLE this Lcom/example/B; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
}
javap 生成的字节码
可以看到flags
中的ACC_BRIDGE, ACC_SYNTHETIC
两个标识。
{
com.example.B();
descriptor: ()V
flags: (0x0000)
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method com/example/A."<init>":()V
4: return
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/example/B;
public java.lang.Integer method();
descriptor: ()Ljava/lang/Integer;
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: iconst_2
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: areturn
LineNumberTable:
line 6: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/example/B;
public java.lang.Number method();
descriptor: ()Ljava/lang/Number;
flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokevirtual #3 // Method method:()Ljava/lang/Integer;
4: areturn
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/example/B;
}
SourceFile: "B.java"
Views: 1,495 · Posted: 2022-04-27
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓
Loading...