У меня есть переменная Scala типа Map [String, Any].
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();
Используя IntelliJ, у меня слишком много вариантов, я просто выбрал scala.collection.immutable.Map
, но я не знаю, как настроить Any
.
Вам нужно "преобразовать" его в 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 не поддерживает примитивные типы в них, так как любой тип T
для JVM всегда поворачивается (стирается) к Object
.
Больше, чем этот scala.collection.immutable.Map<String, Object>
работает без каких-либо явных преобразований:
//Scala
class A {
val a = Map[String, Any]("a" -> 1) //it '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 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
type - not AnyRef
) и AnyRef
как Object
Java, но не наоборот (Object
Java представлен как AnyRef
). Формальный тип Int
может быть представлен как int
и Integer
и т.д.
PS О scala автоматическом боксе для дженериков (например, Int
внутри generic всегда будет отображаться как вложенное в Integer
если оно передано в общий) - единственным исключением являются специализированные методы, но они просто генерируют дополнительные перегруженные unboxed-реализации, поэтому вызов с Java должно быть безопасным в любом случае (так как именно метод, который принимает/возвращает AnyRef
будет AnyRef
).
Any
Java нет ни одного; это scala-специфический тип. Map
Java может иметь только значения 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