你如何从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编译器中的错误

我认为这间接涵盖了它:

伴随对象和Java静态方法

关于伴侣对象还有一件事需要了解。 无论何时定义要用作应用程序入口点的main方法,Scala都要求您将其放在对象中。 但是,在撰写本文时,无法在伴随对象中定义主要方法。 由于生成的代码中的实现细节,JVM将找不到main方法。 此问题可能在将来的版本中得到解决。 现在,您必须在单个对象中定义任何main方法(即“非伴侣”对象)[ScalaTips]。 请考虑下面一个简单的Person类和试图定义main的伴随对象的示例。

如在此处找到: http : //programming-scala.labs.oreilly.com/ch06.html

简而言之,因为你的Object是一个伴侣对象(有一个伴侣类)你不能像你期望的那样调用它。 正如你发现的那样,如果你摆脱了这个课,它就会起作用。

通常最好直接从自己的类访问单例。

在这种情况下:

 org.fun.ScalaPower$.MODULE$.showMyPower(10); 

在不过多介绍实现细节的情况下,Scala可以区分Object和Class / Trait之间的名称空间。 这意味着他们可以使用相同的名称。 但是,对象具有类,因此需要在JVM上具有受损的名称。 当前的Scala约定是在模块名称的末尾添加$(对于顶级模块)。 如果对象是在类中定义的,我相信约定是OuterClass $ ModuleName $。 要强制执行ScalaPower模块的单例属性,还有一个ModuleName $类的静态MODULE $成员。 这是在类加载时初始化的,确保只有一个实例。 这样做的副作用是你不应该在模块的构造函数中进行任何类型的锁定。

无论如何,Scala还内置了一个“为Java创造更好的”静态转发器机制。 这是在ScalaPower类上编写静态方法的地方,它只调用ScalaPower $ .MODULE $ .someMethod()。 如果还定义了伴随类,则可以生成的转发器是有限的,因为不允许在JVM上与静态和实例级方法发生命名冲突。 我认为在2.8.0中这意味着如果你有一个伴侣对象,你将丢失静态转发器。

在这种情况下,“最佳实践”将始终使用ScalaPower $ .MODULE $引用而不是静态转发器,因为转发器可能会随着ScalaPower类的修改而消失。

编辑:错字

你得到的错误是什么? 使用Scala示例和以下Java类:

cat test.java

 import org.fun.*; public class test { public static void main(String args[]) { System.out.println("show my power: " + ScalaPower.showMyPower(3)); } } 

运行如下:

java -cp .:< path-to/scala/install-dir >/lib/scala-library.jar test

给出了我的输出:

show my power: 0, 1, 2

请记住,库存javap工具可用于查看Scala编译器生成的内容。 当然,它并没有直接回答你的问题,但是当你需要的只是提醒代码生成模式时,它就足够了。

做完之后

 class ScalaPower object ScalaPower{ def showMyPower(time:Int) = { (0 to time-1).mkString(", ") } } 

ScalaPower.showMyPower(10)按预期工作。