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

发布于 2024-09-10 04:44:13 字数 757 浏览 0 评论 0原文

我正在尝试将一些 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

掌心的温暖 2024-09-17 04:44:13

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

在这种情况下:

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

编辑:错字

It's usually better to access the singleton directly from its own class.

In this case:

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

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

得不到的就毁灭 2024-09-17 04:44:13

我认为这间接涵盖了它:

伴随对象和 Java 静态
方法

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

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

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

I think this indirectly covers it:

Companion Objects and Java Static
Methods

There is one more thing to know about
companion objects. Whenever you define
a main method to use as the entry
point for an application, Scala
requires you to put it in an object.
However, at the time of this writing,
main methods cannot be defined in a
companion object. Because of
implementation details in the
generated code, the JVM won’t find the
main method. This issue may be
resolved in a future release. For now,
you must define any main method in a
singleton object (i.e., a
“non-companion” object) [ScalaTips].
Consider the following example of a
simple Person class and companion
object that attempts to define main.

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.

停顿的约定 2024-09-17 04:44:13

您遇到了什么错误?
使用 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

给出了我的输出:

显示我的力量:0, 1, 2

What were the errors you were getting?
Using your Scala sample and the following Java class:

cat test.java:


import org.fun.*;

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

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

雪落纷纷 2024-09-17 04:44:13

请记住,常用的 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.

贵在坚持 2024-09-17 04:44:13

执行后

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

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

After doing

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

ScalaPower.showMyPower(10) works as expected.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文