如何从 Java 调用 Scala 单例方法?
我正在尝试将一些 Scala 代码注入到我现有的 Java 应用程序中。 (所以,话虽这么说,我想要更多的乐趣)。
我现在在 Scala 中创建一个单例内容
ScalaPower.scala
package org.fun
class ScalaPower
object ScalaPower{
def showMyPower(time:Int) = {
(0 to time-1).mkString(", ")
}
}
,在 OldJava.java 中,
class OldJava {
public void demo(){
System.out.println(?)
}
}
我应该填写什么 ?
以便 Java 调用 showMyPower 方法? 我尝试了 org.fun.ScalaPower.showMyPower(10) 和 org.fun.ScalaPower.getInstance().showMyPower(10) ,但都不起作用。
(使用 Jad 反编译类文件只显示无意义的代码。)
编辑 我删除了 class ScalaPower 声明,并且 scala 按预期生成了静态方法。 (调用 org.fun.ScalaPower.showMyPower(10) 即可正常工作)。
不知道这是否是scala编译器中的一个错误
I'm trying to inject some Scala code into my existing Java app. (So, being said, I want some more fun).
I create a singleton stuff in Scala
ScalaPower.scala
package org.fun
class ScalaPower
object ScalaPower{
def showMyPower(time:Int) = {
(0 to time-1).mkString(", ")
}
}
Now, inside OldJava.java
class OldJava {
public void demo(){
System.out.println(?)
}
}
What should I fill in ?
so that Java will call the showMyPower method?
I tried both org.fun.ScalaPower.showMyPower(10)
and org.fun.ScalaPower.getInstance().showMyPower(10)
but none work.
(Decompile the class file using Jad show me nothing but nonsense code.)
Edit
I remove the class ScalaPower
declaration and scala produce the static method as expected. (call to org.fun.ScalaPower.showMyPower(10)
just works).
Wonder if it's a bug in scala compiler or not
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
通常最好直接从单例自己的类访问单例。
在这种情况下:
Scala 在不过多关注实现细节的情况下区分了 Object 和 Class/Trait 之间的命名空间。这意味着他们可以使用相同的名称。然而,对象有一个类,因此在 JVM 上需要一个损坏的名称。当前的 Scala 约定是在模块名称末尾添加 $(对于顶级模块)。如果对象是在类中定义的,我相信约定是 OuterClass$ModuleName$。为了强制 ScalaPower 模块的单例属性,ModuleName$ 类还有一个静态 MODULE$ 成员。这是在类加载时初始化的,确保只有一个实例。这样做的副作用是您不应该在模块的构造函数中执行任何类型的锁定。
无论如何,Scala 还内置了一个“让 Java 变得更好”的静态转发器机制。这是在 ScalaPower 类上编写仅调用 ScalaPower$.MODULE$.someMethod() 的静态方法的地方。如果您还定义了伴随类,则可以生成的转发器将受到限制,因为不允许与 JVM 上的静态方法和实例级方法发生命名冲突。我认为在 2.8.0 中这意味着如果你有一个伴随对象,你就会失去你的静态转发器。
在这种情况下,“最佳实践”是始终使用 ScalaPower$.MODULE$ 引用而不是静态转发器,因为转发器可能会随着 ScalaPower 类的修改而消失。
编辑:错字
It's usually better to access the singleton directly from its own class.
In this case:
Without going too much into the implementation details, Scala differentiates namespaces between Object and Class/Trait. This means they can use the same name. However, an object has a class, and therefore needs a mangled name on the JVM. The current Scala conventions is to add a $ at the end of the module name (for top-level modules). If the object is defined in a class, I believe the convention is OuterClass$ModuleName$. To enforce the singleton property of the ScalaPower module, there is also a static MODULE$ member of the ModuleName$ class. This is initialised at class-load time, ensuring that there is only one instance. A side effect of this is that you should not do any sort of locking in a module's constructor.
In any case, Scala also has built into it a "make things nicer for Java" static-forwarders mechanism. This is where it writes static methods on the ScalaPower class that just call ScalaPower$.MODULE$.someMethod(). If you also define a companion class, the forwarders that could be generated are limited, as you are not allowed to have naming conflicts with static and instance-level methods on the JVM. I think in 2.8.0 this means if you have a companion object, you lose your static forwarders.
In this case a "best practice" would be to always use the ScalaPower$.MODULE$ reference instead of a static forwarder, as the forwarder could disappear with modifications to the ScalaPower class.
EDIT: Typo
我认为这间接涵盖了它:
如下所示: http://programming-scala.labs.oreilly.com/ch06.html
简而言之,因为您的对象是一个伴随对象(有一个伴随类),所以您不能像您期望的那样调用它。正如您所发现的,如果您摆脱课程,它就会起作用。
I think this indirectly covers it:
As found here: http://programming-scala.labs.oreilly.com/ch06.html
In short because your Object is a companion object (has a companion class) you can't call it like you expect. As you found if you get rid of the class it will work.
您遇到了什么错误?
使用 Scala 示例和以下 Java 类:
cat test.java
:并按如下方式运行:
java -cp .:path-to/scala/install-dir >/lib/scala-library.jar test
给出了我的输出:
显示我的力量:0, 1, 2
What were the errors you were getting?
Using your Scala sample and the following Java class:
cat test.java
:And running it as follows:
java -cp .:<path-to/scala/install-dir>/lib/scala-library.jar test
gives my the output:
show my power: 0, 1, 2
请记住,常用的 javap 工具可用于查看 Scala 编译器生成的内容。当然,它并不能直接回答您的问题,但是当您需要的只是提醒代码生成模式时,这就足够了。
Keep in mind that the stock
javap
tool can be used to see what the Scala compiler produces. It doesn't directly answer your question, of course, but when what you need is just to be reminded of the code generation patterns, it's sufficient.执行后
ScalaPower.showMyPower(10)
按预期工作。After doing
ScalaPower.showMyPower(10)
works as expected.