在Scala中,给定一个子类,如何使用反射检查它是否覆盖其父接口(在Java中定义)的默认方法?
在上面的代码片段中,我有一个用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()
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