gpt4 book ai didi

java - 为什么在 Java 中调用通用覆盖函数会产生 2 个堆栈帧

转载 作者:行者123 更新时间:2023-12-04 07:38:25 24 4
gpt4 key购买 nike

我注意到有时调用我的覆盖函数会产生两个堆栈帧而不是一个。经过一些实验,我注意到它与泛型返回类型有某种联系。
有一个例子:

public class MyTest {
interface A<T> {
T a();
}

static class AA implements A<String> {
@Override
public String a() {
throw new RuntimeException("fail");
}
}

static void myFun(A<String> a) {
a.a();
}

public static void main(String[] args) {
myFun(new AA());
}
}
并运行这些测试打印:
java.lang.RuntimeException: fail
at MyTest$AA.a(MyTest.java:9)
at MyTest$AA.a(MyTest.java:6)
at MyTest.myFun(MyTest.java:14)
at MyTest.main(MyTest.java:18)
...

如果我用确切的返回类型替换泛型返回类型,例如
public class MyTest {
interface A<T> {
String a();
}

static class AA implements A<String> {
@Override
public String a() {
throw new RuntimeException("fail");
}
}

static void myFun(A<String> a) {
a.a();
}

public static void main(String[] args) {
myFun(new AA());
}
}
产生的异常将如下所示:
java.lang.RuntimeException: fail
at MyTest$AA.a(MyTest.java:9)
at MyTest.myFun(MyTest.java:14)
at MyTest.main(MyTest.java:18)
什么会产生这个额外的堆栈帧 at MyTest$AA.a(MyTest.java:6) (第 6 行是 static class AA implements A<String> {)?
谢谢!
美东时间:
此外,添加泛型参数会产生这种行为。
例如。
public class MyTest {
interface A<T> {
String a(T t);
}

static class AA implements A<String> {
@Override
public String a(String s) {
throw new RuntimeException(s);
}
}

static void myFun(A<String> a) {
a.a("fail");
}

public static void main(String[] args) {
myFun(new AA());
}
}
产生:
java.lang.RuntimeException: fail
at MyTest$AA.a(MyTest.java:9)
at MyTest$AA.a(MyTest.java:6)
at MyTest.myFun(MyTest.java:14)
at MyTest.main(MyTest.java:18)
测试在 Java 11 上运行。
EDT 2:删除测试库

最佳答案

在 J2SE 5.0 之前,Java 没有协变返回类型。 JVM 字节码规则是它覆盖精确的参数匹配,包括返回类型。因此,编译器会插入您所看到的合成桥接方法。
也许令人惊讶的是,JLS 并没有过多地谈论桥接方法。它在 Create Frame, Synchronize, Transfer Control 部分的注释中在表达式章节中。

关于java - 为什么在 Java 中调用通用覆盖函数会产生 2 个堆栈帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67626024/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com