繁体   English   中英

从 Scala AnyVal 类型到 Java 类型的不需要的转换

[英]Unwanted conversion from Scala AnyVal types to Java Types

我正在编写一个函数来获取一些参数并提取它们的类型,但是每当这些参数在 Scala AnyVal (Int, Long, Double, ...) 下时,它们就会被转换为 Java 类型 (Integer, ...)。

这是该函数的一个小例子:

def functionX(args: Any*) = {
   args.map(a => a.getClass)
}

val num: Int = 10

println(num1.getClass) // prints int

println(functionX(num1)) // prints Integer

我应该怎么做才能使所有参数类型(无论它们是 Int 还是 Integer)都处于原始类型而不进行转换?

我还意识到,如果将一个变量放在 Scala 集合中,它也会被转换为 Java 类型:

val num: Int = 1
val numList = List(num)

println(num.getClass) // prints int
println(numList.head.getClass) // prints Integer

是否有任何 Java 自动装箱发生? 但是 Scala 类型,如 Int,不是在 AnyVal 类下,也不是原始类型吗?


为了提供更多关于我为什么要这样做的背景,这里有一个例子:

trait MyTrait {
  def myTraitMethod : String
}

object MyObj extends MyTrait {
  def myTraitMethod = "Works fine"
  def myObjMethod(num1: Int, num2: Int) = num1 * num2
}

case object Manager {
  def currentObj: MyTrait = MyObj
}

val result = Manager.currentObj.myObjMethod
// I wanted to access this object method that is not in Trait, but
// it doesn't seem possible.

我没有做上面代码的最后一行,而是使用反射来做这样的事情:

def executeMethod(obj: MyTrait, methodName: String, args: Any*) = {
    val argTypes = args.map(t => t.getClass)
    val argsObjects = args.map(o => o.asInstanceOf[Object])

    val method = obj.getClass.getMethod(methodName, argTypes:_*)

    method.invoke(obj, argsObjects:_*)

}

val num = 10
val result = executeMethod(Manager.currentObj, "myObjMethod", num1, num2)
// That's where I have problem with Int being converted to Integer
// and the method is not found because it's (Int, Int) and not (Integer, Integer)

functionX是一个函数,它接受可变数量的Any类型的参数。

在某些时候,Scala 将不得不将其编译成一个可以在 JVM 上运行的函数。 该函数将接受一个参数,它将是一个数组或序列类型,因为这就是 JVM 实现变量参数的方式。 事实上,它将是scala.collection.immutable.ArraySeq

您可能了解 JVM 原始类型不是对象。 你不能有一个可以容纳像原始值的单一变量int类似物体String JVM 包括“框”类型IntegerDouble等,因此您可以在必要时使用原始值作为对象。

ArraySeq必须是一些东西的集合,因为在functionX的情况下你说过它可以容纳任何东西,在 JVM 级别,东西必须是Object 由于它是ObjectArraySeq ,因此您想要放入其中的任何原始值都必须装箱。

一旦您意识到 Scala 的Int类型是 JVM 的原始int类型,您观察到的所有行为都会有意义。 它们并不是真正的对象。

为了通过反射调用正确的方法,您可以假设如果参数是Integer类型,那么您应该使用Integer.TYPEclassOf[int]类型来查找方法。 当然,如果您想要的方法实际上采用Integer ,那将会失败。 一旦找到正确的方法,JVM 将负责对参数列表中的所有装箱值进行拆箱。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM