java - 为什么存在这样的方法时会抛出 `NoSuchMethodException`?

标签 java scala reflection jvm anonymous-class

我期待这段代码(在精化类型上使用模式匹配后调用匿名类的方法)

(new {
    def foo : Unit = println("Called foo method")
} : Any) match {
    case f : {def foo : Unit} ⇒
        println("Has foo method")
        f.foo
}

打印

Has foo method
Called foo method

(以及未经检查的警告)。

我知道由于类型删除,匹配总是成功,但这不应该导致问题,因为 f 的运行时类型(即使考虑删除)应该是 $anon $NameOfSomeAnonymousClassThatHasAfooMethod

当进入 Scala REPL (2.9.1) 时,它实际上抛出 NoSuchMethodException:

<console>:11: warning: refinement AnyRef{def foo: Unit} in type pattern AnyRef{def foo: Unit} is unchecked since it is eliminated by erasure
              case f : {def foo : Unit} ⇒
                       ^
Has foo method
java.lang.NoSuchMethodException: $anon$1.foo()
        at java.lang.Class.getMethod(Class.java:1622)
        at .reflMethod$Method1(<console>:13)
        at .<init>(<console>:13)
        at .<clinit>(<console>:13)
        at .<init>(<console>:11)
        at .<clinit>(<console>)
        at $print(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
        at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920)
        at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43)
        at scala.tools.nsc.io.package$$anon$2.run(package.scala:25)
        at java.lang.Thread.run(Thread.java:679)

为什么?

编辑

事实证明,最直接的原因是 foo 被生成为私有(private)的。我在回答中推测了造成这种情况的原因,但我不确定。如果您有任何想法,请随时将其作为答案发布!

最佳答案

I know the match always succeeds due to type erasure, but that shouldn't cause the problem, since the run-time type (even considering erasure) of f should be $anon$NameOfSomeAnonymousClassThatHasAfooMethod

从某种意义上说,它“应该”是显而易见的实现并且是您所期望的;它不需要,正如您所发现的,它不需要。

细化上的模式匹配是盲投。你必须有很大的信心。

This is odd because Scala methods are supposed to be public by default.

您在源代码中声明的方法默认是公开的。实现细节不是。

I suspect the cause is that the compiler wrongly assumes that since the class is anonymous, its defined methods are uncallable from outside the class.

编译器正确地假定您必须违反协议(protocol)条款才能直接调用匿名类的任何方法。您投出您的引用资料并把握机会。

关于java - 为什么存在这样的方法时会抛出 `NoSuchMethodException`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11608526/

相关文章:

reflection - 反射:字符串构造

java - 从 Oracle 数据库中的数百万行中选择的最佳方法

scala 未指定值参数

scala:指定柯里化(Currying)的方法类型

c# - 如何检查方法是否具有属性(使用接口(interface)、转换和抽象)

java - Java 模块指令如何影响对模块的反射访问?

java - 如何检查两个 boolean 值是否相等?

java - Eclipse 在创建 Maven 原型(prototype)项目时不使用最新的快照

java - 修改 REST API 响应以仅包含查询参数中请求的字段

scala - 有什么方法可以将类型保存在 Scala 列表中吗?