gpt4 book ai didi

scala - 从 Any 到 AnyRef 的通用/通用拳击

转载 作者:行者123 更新时间:2023-12-03 14:19:32 24 4
gpt4 key购买 nike

是否可以在 Scala 中动态强制运行时装箱?我想要一个功能:

    def box(value :Any) :AnyRef

或者
    def box[T](value :T) :AnyRef

我有一个通用类,它可以用 AnyVals 参数化,但需要将它们传递给接受对象集合的遗留 Java 方法。当然,我可以自己用模式匹配来实现,但是不得不一次又一次地这样做有点烦人,而且它不适用于用户值(value)类。

编辑

答案既简单又令人惊讶。现在,我可以通过反射(reflection)来做到吗?认为
class Box[T :TypeTag](private var value :T) {
def get :T = value
def set(o :Any) {
...
}
}

我想做一个安全设置,检查运行时是否 o 是 T 的子类,如下所示:
runtimeMirror(getClass.getClassLoader).classSymbol(o.getClass).toType <:< typeOf[T]

不幸的是,对于 Box[Long] 的 typeOf[T] 将是一个原语,下面的检查将在 java.lang.Long 上失败,例如,它是 Seq[Long] 元素的运行时类型。最重要的是,当将泛型与 AnyVals 一起使用时,编译器有时会将它们装箱,使运行时类检查变得不可预测。

最佳答案

只需投到 AnyRefasInstanceOf Scala 会将它变成 AnyRef :

scala> val x = 13
x: Int = 13

scala> val xBoxed = x.asInstanceOf[AnyRef]
xBoxed: AnyRef = 13

scala> xBoxed.getClass()
res0: Class[_ <: AnyRef] = class java.lang.Integer

对于值类,这会将其装箱到值类的实例中,而不是 Java 类中。您可以使用通用 trait 来从您的值类中获取 Java 盒装版本,而无需使用反射。例如:

trait ValueClass[T] extends Any {
def value: T
def javaBoxed: AnyRef = value.asInstanceOf[AnyRef]
}

case class MyInt(value: Int) extends AnyVal with ValueClass[Int]

case class MyReal(asDouble: Double) extends AnyVal with ValueClass[Double] {
def value = asDouble
}

但是,这需要您将特征混合到所有值类中。对于扩展 Product 的值类,就像所有案例类一样,使用 productElement 有一种更快的方法:

def javaBox(x: Product): AnyRef = {
if (x.productArity == 1) x.productElement(0).asInstanceOf[AnyRef]
else x.asInstanceOf[AnyRef] // or throw an exception if you prefer
}

不幸的是,在我看来,这两种方法(mix-in trait 和 Product )都会导致 Scala 进行装箱,这意味着当调用未装箱的值时,该值从未装箱 → Scala 装箱 → 未装箱 → Java 装箱,而不是直接到 Java 装箱值。

关于scala - 从 Any 到 AnyRef 的通用/通用拳击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24757007/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com