[英]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 包括“框”类型Integer
、 Double
等,因此您可以在必要时使用原始值作为对象。
ArraySeq
必须是一些东西的集合,因为在functionX
的情况下你说过它可以容纳任何东西,在 JVM 级别,东西必须是Object
。 由于它是Object
的ArraySeq
,因此您想要放入其中的任何原始值都必须装箱。
一旦您意识到 Scala 的Int
类型是 JVM 的原始int
类型,您观察到的所有行为都会有意义。 它们并不是真正的对象。
为了通过反射调用正确的方法,您可以假设如果参数是Integer
类型,那么您应该使用Integer.TYPE
或classOf[int]
类型来查找方法。 当然,如果您想要的方法实际上采用Integer
,那将会失败。 一旦找到正确的方法,JVM 将负责对参数列表中的所有装箱值进行拆箱。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.