简体   繁体   English

Scala与Java方法调用

[英]Scala vs Java method invocation

I had to write my own JDK dynamic proxy to provide the ability of dynamic interface implementation. 我不得不编写自己的JDK动态代理来提供动态接口实现的能力。 Since I work with akka it has to be written in Scala. 因为我使用akka所以必须用Scala编写。 But I faced with some pretty strange behavior differs from Java: 但是我遇到了一些与Java不同的奇怪行为:

object Main extends App {
    println(classOf[Message].getDeclaredMethod("msg")
                            .invoke(Message("Test"), null)) 
                          //throws IllegalArgumentException
}

case class Message(message: String){
  def msg() = message
}

StackTrace: 堆栈跟踪:

Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at Main$.delayedEndpoint$Main$1(Main.scala:2)
    at Main$delayedInit$body.apply(Main.scala:1)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:381)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
    at scala.App$class.main(App.scala:76)
    at Main$.main(Main.scala:1)
    at Main.main(Main.scala)

DEMO DEMO

But I in Java it works fine: 但我在Java中工作正常:

public static void main (String[] args) throws java.lang.Exception
{
    System.out.println(Message.class.getDeclaredMethod("msg")
              .invoke(new Message(), null)); //prints Message
}

public static class Message{
    public String msg(){
        return "Message";
    }
}

DEMO DEMO

Why does Scala throw exception? 为什么Scala会抛出异常? And how to fix it? 以及如何解决它?

Hopefully I can demonstrate what is going on: 希望我能证明发生了什么:

class TheClass { 
  def theMethod:Unit = { println("It's me the method"); } 
}

scala> classOf[TheClass].getDeclaredMethod("theMethod").invoke(new TheClass, null)
java.lang.IllegalArgumentException: wrong number of arguments
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

scala> classOf[TheClass].getDeclaredMethod("theMethod").invoke(new TheClass)
It's me the method
res1: Object = null

As expected, but now have a look at this: 不出所料,但现在看看这个:

scala> classOf[TheClass]
      .getDeclaredMethod("theMethod").invoke(new TheClass, Array.empty)
java.lang.IllegalArgumentException: wrong number of arguments

Versus this: 对此:

scala> classOf[TheClass]
       .getDeclaredMethod("theMethod").invoke(new TheClass, Array.empty : _*)
It's me the method
res4: Object = null

Notice the difference between the invokes: .invoke(new TheClass, Array.empty) vs .invoke(new TheClass, Array.empty : _*) . 注意调用之间的区别: .invoke(new TheClass, Array.empty) vs .invoke(new TheClass, Array.empty : _*) What happens is that invoke s second argument is a varargs , which should be turned into a array under the hood, when it's given a plain Array.empty or null scalac is replacing them with Array(Array.empty) and Array(null) . 发生的事情是invoke第二个参数是一个varargs ,当它被赋予一个普通的Array.emptynull scalac用Array(Array.empty)Array(null)替换它们时,它应该变成一个数组。 When the argument is not provided it's actually Array.empty and when we use : _* it just telling the compiler that the argument we are proving is the varargs itself. 当没有提供参数时,它实际上是Array.empty ,当我们使用: _*它只是告诉编译器我们证明的参数 varargs本身。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM