簡體   English   中英

如何在Java中創建空的不可變Scala映射?

[英]How do I create an empty immutable Scala map in Java?

這應該是一個顯而易見的,但我還沒有找到一個優雅的解決方案。 由於各種原因,我需要創建一個不可變的Scala映射(來自Scala 2.10的scala.collection.immutable.Map),但我只能編寫Java代碼。 我該怎么做呢?

狂野的猜測 - 這里什么都沒有:

scala.collection.immutable.Map$.MODULE$.<…, …>empty()

起初我很困惑,只是做以下事情會失敗:

scala.collection.immutable.Map<Integer, String> = scala.collection.immutable.Map$.<Integer, String>empty();

它看起來很奇怪的原因是因為我知道scala生成靜態轉發器,在內部取消引用MODULE$並調用相應的(非靜態)方法。 我做了一些測試,雖然我發現它與原始問題有些相似,但它仍然是相關的,也很有用。

假設我們有以下內容:

package test
object MyScalaObject {
  def empty[A, B]: Map[A, B] = sys.error("TODO")
}

使用javap我們可以看到生成了一個靜態轉發器:

public class test.MyScalaObject extends java.lang.Object{
    public static scala.collection.immutable.Map empty();
    public test.MyScalaObject();
}

事實上,我們可以在java中執行以下操作:

scala.collection.immutable.Map<Integer, String> myMap = test.MyScalaObject.<Integer, String>empty();

一切都很好。 但是,如果我們添加一個類或特性MyScalaObject ,它也定義了一個具有相同簽名的方法,scala不會生成靜態轉發器(當然因為JVM不允許類同時定義靜態和非靜態方法)簽名)。 可能還有其他不同的細微情況會阻止生成靜態轉發器。

考慮:

package test
class MyScalaObject {
  def empty[A, B]: Map[A, B] = sys.error("TODO")
}
object MyScalaObject {
  def empty[A, B]: Map[A, B] = sys.error("TODO TOO")
}

javap顯示靜態轉發器確實消失了:

public class test.MyScalaObject extends java.lang.Object{
    public scala.collection.immutable.Map empty();
    public test.MyScalaObject();
}

在這種情況下,它意味着我們必須明確地取消引用$MODULE ,它指向單例對象的(唯一)實例:

scala.collection.immutable.Map<Integer, String> myMap = test.MyScalaObject$.MODULE$.<Integer, String>empty();

事實證明,特征scala.collection.immutable.Map及其伴隨對象都定義了一個無參數的empty方法,因此我們偶然發現了這個問題。

道德是雖然靜態轉發器是一個潛在有用的特性,但它也非常脆弱,因為僅修改類的事實(在這種情況下,在類MyScalaObject添加一個empty方法)可以破壞該特征,甚至不會觸及它的伴隨對象本身。 因此,總是明確地引用MODULE$ (如Wilfred Springer的答案),即使它看起來不那么好,即使靜態轉發器當前存在,也是一個好主意,以防止在更新到更新版本的庫時可能發生破壞。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM