Java 语法糖 - 方法重写时的桥接方法
Java 大约 3711 字桥接方法
子类重写的方法的返回值可以是父类方法的返回值的子类。
本质
编译器帮忙生成了合成的桥接方法。
内部有一个重写父类相同返回值的方法,以及子类重写的返回值类型的方法。
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"
阅读 553 · 发布于 2022-04-27
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb扫描下方二维码关注公众号和小程序↓↓↓

昵称:
随便看看
换一批
-
Elasticsearch 轻量搜索 _search 和 q=阅读 2978
-
Java 并发编程之 Phaser阅读 2216
-
记一次小程序排查 setData 函数耗时很长思路阅读 2963
-
Docker 部署 Alertmanager阅读 2743
-
Element UI DatePicker 时间跨度限制在同一个月内阅读 4895
-
Java 并发编程之 AQS ReentrantLock 公平锁源码解析阅读 1068
-
Docker 部署 Kibana阅读 816
-
OpenResty 整合 LuaRocks - Windows10阅读 2767
-
Spring Boot 整合 Log4j2 不起作用阅读 1408
-
SQL 注入和 XSS 攻击阅读 2308