你如何从Java调用Scala单例方法?

时间:2010-07-19 15:47:49

标签: java scala interop scala-java-interop

我正在尝试将一些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编译器中的错误

5 个答案:

答案 0 :(得分:17)

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

在这种情况下:

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类的修改而消失。

编辑:错字

答案 1 :(得分:10)

你得到的错误是什么? 使用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

答案 2 :(得分:9)

我认为这间接涵盖了它:

  

伴随对象和Java静态   方法

     

还有一件事需要了解   伴侣物体。每当你定义   用作条目的主要方法   对于一个应用程序,Scala   要求你把它放在一个对象中。   但是,在撰写本文时,   主要方法无法在a中定义   伴侣对象。因为   实施细节   生成代码后,JVM就找不到了   主要方法。这个问题可能是   在将来的版本中解决。目前,   你必须在a中定义任何main方法   单身对象(即a   “非伴侣”对象)[ScalaTips]。   考虑以下a的例子   简单的Person类和伴侣   尝试定义main的对象。

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

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

答案 3 :(得分:3)

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

答案 4 :(得分:1)

完成后

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

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