在Scala中,给定一个子类,如何使用反射检查它是否覆盖其父接口(在Java中定义)的默认方法?

在Scala中,给定一个子类,如何使用反射检查它是否覆盖其父接口(在Java中定义)的默认方法?,java,scala,reflection,Java,Scala,Reflection,在上面的代码片段中,我有一个用Java定义的接口,带有一个默认方法bar,它只是抛出异常。问题是如何检查子类FooImpl是否覆盖默认方法。在Java中,我们似乎可以通过反射检查方法实例上的声明类:如果FooImpl覆盖该方法,则声明类将是它自己,否则将是接口Foo 然而,在Scala(2.12)中,上述情况似乎不正确:在这两种情况下,声明类都将是FooImpl,例如,如果我有如下内容: (defined in Java) interface Foo { default int bar()

在上面的代码片段中,我有一个用Java定义的接口,带有一个默认方法
bar
,它只是抛出异常。问题是如何检查子类
FooImpl
是否覆盖默认方法。在Java中,我们似乎可以通过反射检查
方法
实例上的声明类:如果
FooImpl
覆盖该方法,则声明类将是它自己,否则将是接口
Foo


然而,在Scala(2.12)中,上述情况似乎不正确:在这两种情况下,声明类都将是
FooImpl

,例如,如果我有如下内容:

(defined in Java)
interface Foo {
  default int bar() {
    throw new RuntimeException("not implemented");
  }
}

(defined in Scala)
class FooImpl extends Foo {
  override int bar() {
    return 42;
  }
}
我可以通过以下方式确定
方法m
是否是您要查找的方法:

interface Test {
    default void go() {

    }
}

static class Impl implements Test, AutoCloseable {

    @Override
    public void go() {

    }

    @Override
    public void close() throws Exception {

    }
}
私有静态布尔值IsDefaultandOverrided(方法m,类cls){
类[]接口=ClassUtils.getAllInterfacesForClass(cls);
System.out.println(数组.toString(接口));
返回Arrays.stream(接口)
.flatMap(在->数组.stream(在.getDeclaredMethods()中)
.filter(方法::isDefault)
.filter(method->method.getName().equals(m.getName()))
.filter(方法->方法.getReturnType()==m.getReturnType())
.filter(方法->数组.equals(方法.getParameterTypes(),m.getParameterTypes())
.count()==1;
}    

我使用
Spring
中的
ClassUtils
来获取类实现的所有接口,不管是直接的还是非直接的。有许多库也公开了这样的功能(但自己编写并没有那么复杂)

。getDeclarignClass
对我来说似乎很好

这就是我所做的。 在java中:

在scala中:

interface Foo {
   default String bar() {
      return "bar";
   }
   default String baz() {
     return "baz";
   }
}
这张照片是:

class Bar extends Foo {
    override def bar() = "baz"
}

object Bar {
    def main(argv: Array[String]) = classOf[Bar]
      .getMethods.filter(_.getName.startsWith("ba"))
      .map { m => m.getName -> m.getDeclaringClass.getName }
      .foreach(println)
}
因此,类似这样的方法应该会奏效:

(bar,Bar)
(baz,Foo)

你为什么想知道?您总是可以按照正常的覆盖规则检查方法名和参数类型。很抱歉,我忘了提到我在Scala中检查了这个问题-我假设Java和Scala在这方面应该有相同的行为,但显然这不是真的。在Java中,我似乎可以通过使用
方法来轻松检查这一点。getDeclaringClass
但是在Scala中,声明类总是相同的。谢谢!很抱歉,我忘了提到我使用的是Scala,它在父接口的默认方法方面似乎有不同的行为。将编辑我的问题。似乎用Java我们也可以检查
方法.getDeclaringClass
。谢谢。嗯,我试过了,但对我来说,这两种情况都会返回
Bar
。您使用的是哪个版本的Scala?我想知道是什么原因造成了这种差异。2.13和2.12都能正常工作。我非常怀疑它与scala版本有关,因为这个方法是java的本机实现。这对我从来都不管用。我在一个简单的Maven项目中有相同的代码设置,它总是为Bar和baz方法打印Bar。请尝试在项目之外执行。只需将上面显示的代码片段粘贴到两个文件中,从命令行编译并运行,无需maven或其他任何东西。如果这不起作用,我想问一下您使用的是什么jdk:/我试过了-它还是一样的。顺便说一句,我试过JDK 8和11。
(bar,Bar)
(baz,Foo)
    def isOverridden(mtd: Method, clazz: Class) = 
       mtd.getDeclaringClass == clazz