加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 类#getDeclaredMethods()返回继承的方法

发布时间:2020-12-14 05:53:06 所属栏目:Java 来源:网络整理
导读:参见英文答案 getDeclaredMethods() behaving differently in Java 7 vs. Java 81个 考虑下一个代码: interface A { A setX(Object x); A setY(Object y);}interface B extends A { B setX(Object x);} 如果您尝试将B.class.getDeclaredMethods()与jdk8一起
参见英文答案 > getDeclaredMethods() behaving differently in Java 7 vs. Java 81个
考虑下一个代码:
interface A {
    A setX(Object x);
    A setY(Object y);
}

interface B extends A {
    B setX(Object x);
}

如果您尝试将B.class.getDeclaredMethods()与jdk8一起使用
你会得到下一个方法:

公共抽象B B.setX(java.lang.Object)和
public default A B.setX(java.lang.Object)

Javadoc说Class#getDeclaredMethods()只返回DECLARED方法,那么为什么返回2个方法呢?如果有人有解释,为什么第二种方法有’默认’修饰符?

我应该发布一个bug报告吗?
这个问题非常接近to this one,但影响版本是jdk6,对于jdk7,它工作正常(返回单个方法)

解决方法

我不会说这是一个错误.当您的B接口由javac编译时,它会添加一个返回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()正确地返回它.对于这个额外的方法,isBridge()和isSynthetic()调用将返回true,因此如果你不喜欢它,你可以根据它来过滤它.

桥接方法对于正确实现协变返回类型很有用,因为JVM不了解此功能.它们是必需的,以协变返回类型将虚拟调用分派给方法. Java 1.8中出现的新桥接方法有助于支持默认方法的协变返回类型.子接口可以定义setX的默认实现,在这种情况下,需要自动生成的桥接方法来正确地将调用分派给该实现.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读