Class#getDeclaredMethods() returns 继承方法
Class#getDeclaredMethods() returns inherited methods
考虑下一个代码:
interface A {
A setX(Object x);
A setY(Object y);
}
interface B extends A {
B setX(Object x);
}
如果您尝试将 B.class.getDeclaredMethods()
与 jdk8 一起使用
您将获得下一个方法:
public 摘要 B B.setX(java.lang.Object) 和
public默认AB.setX(java.lang.Object)
Javadoc 说 Class#getDeclaredMethods()
returns 只有 DECLARED 方法那么为什么返回 2 个方法?如果有人有解释那么为什么第二种方法有 'default' 修饰符?
我应该 post 报告错误吗?
这个问题非常接近 to this one 但影响版本是 jdk6 并且对于 jdk7 它工作正常(returns 单一方法)
我不会说这是一个错误。当您的 B
接口被 javac 编译时,它添加了一个合成桥接方法,即 returns A
。您可以通过检查 javap 输出看到这一点:
$ javap -c B
Compiled from "B.java"
interface B extends A {
public abstract B setX(java.lang.Object);
public A setX(java.lang.Object);
Code:
0: aload_0
1: aload_1
2: invokeinterface #1, 2 // InterfaceMethod setX:(Ljava/lang/Object;)LB;
7: areturn
}
在Java 1.7中当然没有这样的方法,因为在Java中不可能创建默认方法。因此,在 1.7 中编译时,您会得到以下内容:
$ javap -c B
Compiled from "B.java"
interface B extends A {
public abstract B setX(java.lang.Object);
}
但是在 Java 1.8 中,这个额外的方法实际上是在字节码中声明的,所以 getDeclaredMethods()
正确地 return 了它。对于此附加方法,isBridge()
和 isSynthetic()
调用将 return 为真,因此如果您不喜欢它,可以根据此过滤掉它。
桥接方法对于正确实现协变 return 类型很有用,因为 JVM 不知道此功能。它们是将虚拟调用分派到具有协变 return 类型的方法所必需的。 Java 1.8 中出现了新的桥接方法,有助于支持默认方法的协变 return 类型。子接口可以为 setX
定义一个默认实现,在这种情况下,自动生成的桥接方法将是正确分派对该实现的调用所必需的。
考虑下一个代码:
interface A {
A setX(Object x);
A setY(Object y);
}
interface B extends A {
B setX(Object x);
}
如果您尝试将 B.class.getDeclaredMethods()
与 jdk8 一起使用
您将获得下一个方法:
public 摘要 B B.setX(java.lang.Object) 和 public默认AB.setX(java.lang.Object)
Javadoc 说 Class#getDeclaredMethods()
returns 只有 DECLARED 方法那么为什么返回 2 个方法?如果有人有解释那么为什么第二种方法有 'default' 修饰符?
我应该 post 报告错误吗? 这个问题非常接近 to this one 但影响版本是 jdk6 并且对于 jdk7 它工作正常(returns 单一方法)
我不会说这是一个错误。当您的 B
接口被 javac 编译时,它添加了一个合成桥接方法,即 returns A
。您可以通过检查 javap 输出看到这一点:
$ javap -c B
Compiled from "B.java"
interface B extends A {
public abstract B setX(java.lang.Object);
public A setX(java.lang.Object);
Code:
0: aload_0
1: aload_1
2: invokeinterface #1, 2 // InterfaceMethod setX:(Ljava/lang/Object;)LB;
7: areturn
}
在Java 1.7中当然没有这样的方法,因为在Java中不可能创建默认方法。因此,在 1.7 中编译时,您会得到以下内容:
$ javap -c B
Compiled from "B.java"
interface B extends A {
public abstract B setX(java.lang.Object);
}
但是在 Java 1.8 中,这个额外的方法实际上是在字节码中声明的,所以 getDeclaredMethods()
正确地 return 了它。对于此附加方法,isBridge()
和 isSynthetic()
调用将 return 为真,因此如果您不喜欢它,可以根据此过滤掉它。
桥接方法对于正确实现协变 return 类型很有用,因为 JVM 不知道此功能。它们是将虚拟调用分派到具有协变 return 类型的方法所必需的。 Java 1.8 中出现了新的桥接方法,有助于支持默认方法的协变 return 类型。子接口可以为 setX
定义一个默认实现,在这种情况下,自动生成的桥接方法将是正确分派对该实现的调用所必需的。