Scala编译器问题还是JVM装箱子问题?

Scala编译器问题还是JVM装箱子问题?,scala,jvm,boxing,Scala,Jvm,Boxing,下面的函数是一些代码的一部分,我必须与一个特别讨厌的(如非类型化的)JavaAPI接口。它的目的是在上下文“知道”类型应该是什么的情况下安全地执行强制转换,但我想确保在运行时在某些未知的边缘情况下不会出现错误的故障模式: def safeCast[A](o: Any): Option[A] = Try(o.asInstanceOf[A]).toOption $ echo 'class Demo { def safeCast[A](o: Any) = o.asInstanceOf[A] }'

下面的函数是一些代码的一部分,我必须与一个特别讨厌的(如非类型化的)JavaAPI接口。它的目的是在上下文“知道”类型应该是什么的情况下安全地执行强制转换,但我想确保在运行时在某些未知的边缘情况下不会出现错误的故障模式:

def safeCast[A](o: Any): Option[A] =
  Try(o.asInstanceOf[A]).toOption
$ echo 'class Demo { def safeCast[A](o: Any) = o.asInstanceOf[A] }' > test.scala
$ scalac test.scala
$ cfr test.scala
$ javap -c Demo
Compiled from "test.scala"
public class Demo {
  public <A> A safeCast(java.lang.Object);
    Code:
       0: aload_1
       1: areturn

  public Demo();
    Code:
       0: aload_0
       1: invokespecial #18                 // Method java/lang/Object."<init>":()V
       4: return
}
现在看看在REPL会话中使用时会发生什么:

scala> val testDouble: Double = 1.0

testDouble: Double = 1.0

scala> safeCast[Int](testDouble)

res0: Option[Int] = Some(1.0)
res0
声称具有类型
选项[Int]
但值
一些(1.0)
(即-
一些[Double]
)。如果我们试图映射到此选项,则会出现类强制转换异常

此行为仅在多态的安全广播中发生。如果我们拧紧到特定类型:

def safeIntCast(o: Any): Option[Int] = Try(o.asInstanceOf[Int]).toOption
然后我们得到:

scala> safeIntCast(testDouble)

res1: Option[Int] = None
因此,多态性在某种程度上与装箱(我怀疑???)或编译器问题(bug???)相互作用。使用的编译器版本为2.12.2

有人能对此做出解释吗?

请参阅和,以供进一步参考。它解释了很多有关Scala asInstanceOf的内容

希望有帮助

请参阅和以获取更多参考。它解释了很多有关Scala asInstanceOf的内容


希望有帮助

这是因为类型擦除,类型T在运行时是未知的。当您映射类型时,类型是已知的(因为它是经过计算的),您将得到ClassCastException

但您可以使用class标记在运行时获取类型:

import scala.reflect.ClassTag
import scala.util.Try

object Application extends App {

  def safeCast[A](o: Any)(implicit ct: ClassTag[A]): Option[A] =
    Try(ct.runtimeClass.cast(o).asInstanceOf[A]).toOption

}

这是因为类型擦除,类型T在运行时是未知的。当您映射类型时,类型是已知的(因为它是经过计算的),您将得到ClassCastException

但您可以使用class标记在运行时获取类型:

import scala.reflect.ClassTag
import scala.util.Try

object Application extends App {

  def safeCast[A](o: Any)(implicit ct: ClassTag[A]): Option[A] =
    Try(ct.runtimeClass.cast(o).asInstanceOf[A]).toOption

}

对于泛型类型
A
,没有[A]的安装,它只是在运行时消失:

def safeCast[A](o: Any): Option[A] =
  Try(o.asInstanceOf[A]).toOption
$ echo 'class Demo { def safeCast[A](o: Any) = o.asInstanceOf[A] }' > test.scala
$ scalac test.scala
$ cfr test.scala
$ javap -c Demo
Compiled from "test.scala"
public class Demo {
  public <A> A safeCast(java.lang.Object);
    Code:
       0: aload_1
       1: areturn

  public Demo();
    Code:
       0: aload_0
       1: invokespecial #18                 // Method java/lang/Object."<init>":()V
       4: return
}
$echo'类演示{def safeCast[A](o:Any)=o.asInstanceOf[A]}>test.scala
$scalac test.scala
$cfr test.scala
$javap-c演示
从“test.scala”编译而来
公开课演示{
公共安全广播(java.lang.Object);
代码:
0:aload_1
1:轮到你了
公开演示();
代码:
0:aload_0
1:invokespecial#18//方法java/lang/Object。“:()V
4:返回
}

对于泛型类型
A
,不存在[A]的替代物,它只是在运行时消失:

def safeCast[A](o: Any): Option[A] =
  Try(o.asInstanceOf[A]).toOption
$ echo 'class Demo { def safeCast[A](o: Any) = o.asInstanceOf[A] }' > test.scala
$ scalac test.scala
$ cfr test.scala
$ javap -c Demo
Compiled from "test.scala"
public class Demo {
  public <A> A safeCast(java.lang.Object);
    Code:
       0: aload_1
       1: areturn

  public Demo();
    Code:
       0: aload_0
       1: invokespecial #18                 // Method java/lang/Object."<init>":()V
       4: return
}
$echo'类演示{def safeCast[A](o:Any)=o.asInstanceOf[A]}>test.scala
$scalac test.scala
$cfr test.scala
$javap-c演示
从“test.scala”编译而来
公开课演示{
公共安全广播(java.lang.Object);
代码:
0:aload_1
1:轮到你了
公开演示();
代码:
0:aload_0
1:invokespecial#18//方法java/lang/Object。“:()V
4:返回
}