簡體   English   中英

Scala asInstanceOf泛型類型在Try中不會失敗

[英]Scala asInstanceOf generic type does not fail in Try

嘗試將String轉換為Double顯然會失敗:

scala> Try("abc".asInstanceOf[Double])
res11: scala.util.Try[Double] = Failure(java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Double)

但是,如果我將以上定義為函數:

scala> def convertAsTypeOf[T](anyValue: Any): Try[T] = Try(anyValue.asInstanceOf[T])
convertAsTypeOf: [T](anyValue: Any)scala.util.Try[T]

奇怪的是,當我嘗試將String轉換為Double時,它返回Success:

scala> convertAsTypeOf[Double]("abc")
res10: scala.util.Try[Double] = Success(abc)

如果我試圖從成功中獲取價值,則會出現以下異常:

scala> convertAsTypeOf[Double]("abc").get
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Double
        at scala.runtime.BoxesRunTime.unboxToDouble(BoxesRunTime.java:119)

為什么會這樣? 在通用函數中,有什么方法可以解決這個問題並使其成為asInstanceOf[T]

由於類型擦除,類型T在運行時是未知的,因此asInstanceOf不能實際檢查其類型轉換。 實際上,它作為無操作編譯。 但是,最終完成.get時,將對Double進行.get類型轉換,並且由於這里知道類型,因此我們可以獲得ClassCastException

如果更改convertAsTypeOf使用ClassTag

def convertAsTypeOf[T](anyValue: Any)(implicit tag: ClassTag[T]): Try[T] =
  Try(tag.runtimeClass.cast(anyValue).asInstanceOf[T])

然后,您將在預期的時候得到錯誤:

scala> convertAsTypeOf[Double]("abc")
res1: scala.util.Try[Double] = Failure(java.lang.ClassCastException: Cannot cast java.lang.String to double)

ClassTag在運行時表示類型T ,從而可以根據該值檢查值。

發生這種情況的原因是類型擦除,這使得通用T的asInstanceOf [T]無效。 我不知道為什么編譯器不會發出任何警告。

您可以使用ClassTag強制進行檢查。 像這樣:

import reflect.ClassTag

def convertAsTypeOf[T : ClassTag](anyValue: Any): Try[T] = Try {
    anyValue match { case t: T => t }
}

之所以可行,是因為如果大小寫匹配,編譯器將使用隱式ClassTag(如果可用)(如果不可用,則生成警告)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM