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

2022-09-01 17:08:56

我试图将一些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 反编译类文件,只向我显示无意义的代码。

编辑我删除了声明,scala按预期生成静态方法。(调用只是工作)。class ScalaPowerorg.fun.ScalaPower.showMyPower(10)

想知道它是否是scala编译器中的一个错误


答案 1

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

在这种情况下:

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

在没有太多讨论实现细节的情况下,Scala区分了对象和类/特征之间的命名空间。这意味着它们可以使用相同的名称。但是,对象有一个类,因此需要在 JVM 上有一个残缺的名称。当前的 Scala 约定是在模块名称的末尾添加 $(对于顶级模块)。如果对象是在类中定义的,我相信约定是OuterClass$ModuleName$。为了强制 ScalaPower 模块的单例属性,ModuleName$ 类还有一个静态 MODULE$ 成员。这在类装入时初始化,确保只有一个实例。这样做的副作用是,您不应该在模块的构造函数中执行任何类型的锁定。

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

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

编辑:错别字


答案 2

我认为这间接涵盖了它:

伴随对象和 Java 静态方法

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

如这里所示:http://programming-scala.labs.oreilly.com/ch06.html

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


推荐