将具有任何类型的Scala的Map分配给Java变量

时间:2015-04-11 16:33:55

标签: java scala

我有一个类型为Map [String,Any]的Scala变量。

object Maps
{
  var no_string: Map[String, Any] = Map(
  ...

我还有一个使用此类型作为参数的Scala方法。

def generateContext(rep: Map[String, Any], m: Int, k: Int, q: Int) : Array[Byte]

在Java中,我可以使用如下类型调用方法。

wifi.generateContext(Maps.no_string(), m, k, q);

然后,如何将Maps.no_string()存储到Java变量中?换句话说,我需要用什么类型来存储它们?

Map(???)[String, Any(???)] x = Maps.no_string();

enter image description here

使用IntelliJ,我有太多选项,我只选择了scala.collection.immutable.Map,但我不知道如何设置Any

2 个答案:

答案 0 :(得分:2)

您需要将其“转换”为Map[String, AnyRef],对应scala.collection.immutable.Map<String, Object>

scala> val a: Map[String, Any] = Map("a" -> 1)
a: Map[String,Any] = Map(a -> 1)

scala> val b: Map[String, AnyRef] = a.asInstanceOf[Map[String, AnyRef]]
b: Map[String,AnyRef] = Map(a -> 1)

scala> b("a") //no ClassCastException as there is nothing to cast
res7: AnyRef = 1

通用类型的装箱在Scala中自动完成,其中包含Java doesn't support基元类型,因为JVM的任何类型T始终被转换(擦除)到Object

除了scala.collection.immutable.Map<String, Object>以外,没有任何明确的转化:

//Scala
class A {
  val a = Map[String, Any]("a" -> 1) //it's `Any` but fits to AnyRef/Object
}

//Java
public class B {
    public static void main(String[] args) {
        A a = new A();
        scala.collection.immutable.Map<String, Object> map = a.a(); //it's AnyRef/Object and btw fits only to AnyRef if you'd try to use it from Scala
        System.out.println("Hello World!" + map.apply("a"));
    }
}

打印:

Hello World!1

显然,scala代表Any(完全正式Any类型 - 不是子类型)和AnyRef代表Java Object,但反之亦然(Java Object }仅表示为AnyRef。正式Int类型可以由intInteger表示,依此类推。

P.S。关于scala的泛型自动装箱(例如,泛型中的Int将始终表示为盒装Integer,如果它被传递给泛型) - 唯一的例外是专门的方法,但它们只是生成额外的重载未装箱实现,所以来自Java的调用无论如何都应该是安全的(正如选择/返回AnyRef的方法一样)。

答案 1 :(得分:0)

Java中不存在

Any;它是特定于scala的类型。 Java的Map只能有Object个值(对应于scala的AnyRef),而不是原语,因此您需要进行更仔细的转换:

val m = Map[String, Any]("a" -> 1, "b" -> "two")
import scala.collection.JavaConverters._
val javaMap: java.util.Map[String, java.lang.Object] = 
  m.mapValues {
    case x: AnyRef => x: java.lang.Object
    case x: Int => Integer.valueOf(x)
    // etc for other primatives...
  }.asJava