2010-07-19 56 views
21

我正在嘗試將一些Scala代碼注入到我現有的Java應用程序中。 (所以,據說,我想要更多樂趣)。如何從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),但都沒有工作。

(使用反編譯亞德類文件告訴我什麼,但廢話代碼。)

編輯 我刪除class ScalaPower聲明和Scala產生的靜態方法如預期。 (致電org.fun.ScalaPower.showMyPower(10)只是工作)。

不知道是否是在Scala編譯器錯誤或不

+1

什麼'org.fun.ScalaPower.showMyPower(10)'? – OscarRyz 2010-07-19 16:55:01

+0

哎喲,我的壞。忘了更改名稱空間。已經更新了這個問題。謝謝。 – 2010-07-20 06:34:50

+1

順便說一下,你可以寫'0直到時間'而不是'0到時間1'。 – 2011-02-10 08:27:37

回答

9

我認爲這間接地覆蓋它:

伴侶對象和Java靜態 方法

有一兩件事要了解 伴侶的對象。每當你定義一個主要方法 作爲條目 指向一個應用程序,斯卡拉 要求你把它放在一個對象。 但是,在撰寫本文時, 主要方法無法在 伴隨對象中定義。由於 生成的代碼中的 實現細節,JVM將找不到 主要方法。在未來的版本中可能會解決此問題 。目前, 您必須在一個 單例對象(即,一個 「非伴隨」對象)[ScalaTips]中定義任何主要方法。 考慮下面的示例,該示例試圖定義main的 簡單Person類和伴隨 對象。

由於這裏找到:http://programming-scala.labs.oreilly.com/ch06.html

總之,因爲你的對象是一個同伴對象(有一個伴侶應用類)就像你期望你不能調用它。正如你發現,如果你擺脫了課程,它會起作用。

+2

這不再是事實。在寫作時和斯卡拉2之間。8發佈後,轉發代碼生成模式被固定,以允許在同伴中使用主要方法。 – 2010-07-20 15:23:35

+0

哦,非常好。這本書暗示他們希望它會被改變,但沒有說2.8(他們很期待2.8-ness)。 這就是說原始的提問者沒有給他的版本,並從他的「編輯我刪除類ScalaPower聲明和Scala產生預期的靜態方法。」它仍然聽起來可能是這個問題。 – 2010-07-20 16:46:33

+0

謝謝。這解釋了我的情況。我現在正在轉換到scala 2.8。地獄,eclipse scala插件仍然很糟糕。 – 2010-07-20 17:57:08

3

請記住,股票javap工具可以用來查看Scala編譯器產生什麼。當然,它並不直接回答你的問題,但是當你需要的是提醒代碼生成模式時,這就足夠了。

+0

謝謝。當我回家時我會嘗試。 (現在工作) – 2010-07-20 06:39:37

10

你得到的錯誤是什麼? 使用您的斯卡拉樣品和下面的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

+1

嗯,這很奇怪。我的代碼甚至沒有編譯。它是說''符號'showMyPower'沒有找到'(儘管IDEA Scala插件理解它,並提供了一個自動完成) – 2010-07-20 06:37:33

+0

我發現實際上'showMyPower'方法是在Scala $中聲明的,而不是Scala。您正在使用哪個版本的Scala使這些代碼可編譯?我正在使用2.7.5 – 2010-07-20 12:45:18

+0

Ouch,'org.fun.ScalaPower $ .MODULE $ .showMyPower'確實是我應該調用的正確方法,那是什麼? – 2010-07-20 12:56:35

1

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

ScalaPower.showMyPower(10)按預期工作後。

14

通常直接從自己的類訪問單身人士通常會更好。

在這種情況下:

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

沒有去過多的實現細節,斯卡拉區分對象和類/性狀之間的命名空間。這意味着他們可以使用相同的名稱。但是,一個對象有一個類,因此需要在JVM上有一個重名的名稱。當前的Scala約定是在模塊名稱末尾添加一個$(用於頂層模塊)。如果該對象是在一個類中定義的,我相信這個約定是OuterClass $ ModuleName $。爲了強制執行ScalaPower模塊的單例屬性,ModuleName $類還有一個靜態MODULE $成員。這是在類加載時初始化的,確保只有一個實例。這樣做的一個副作用是你應該在模塊的構造函數中做任何類型的鎖定,而不是而不是。在任何情況下,Scala還內置了一個「爲Java創造更好的」靜態轉發機制。這就是它在ScalaPower類上寫靜態方法的地方,它只是調用ScalaPower $ .MODULE $ .someMethod()。如果您還定義了一個伴隨類,那麼可能會生成的轉發器是有限的,因爲您不允許在JVM上與靜態和實例級方法命名衝突。我認爲在2.8.0這意味着如果你有一個伴侶對象,你會失去靜態轉發器。

在這種情況下,「最佳做法」是始終使用ScalaPower $ .MODULE $引用而不是靜態轉發器,因爲轉發器可能隨着對ScalaPower類的修改而消失。

編輯:錯字

+0

這裏的代碼在MODULE $中有一個錯字 – 2013-11-29 17:23:54