16

次のような配列があるとしましょう*:

val foo: Any = 1 : Int
Option(foo.asInstanceOf[String])

明らかな理由で失敗します:

// java.lang.ClassCastException: java.lang.Integer cannot be cast to 
// java.lang.String
// ... 48 elided

次に、次のクラスを考えてみましょう。

case class DummyRow() {
  val foo: Any = 1 : Int
  def getAs[T] = foo.asInstanceOf[T]
  def getAsOption[T] = Option(foo.asInstanceOf[T])
}

私が知る限りgetAs、前の のapply後にasInstanceOf.

驚くべきことに、そうではありません。単独で呼び出すと、例外がスローされます。

DummyRow().getAs[String]
// java.lang.ClassCastException: java.lang.Integer cannot be cast to 
// java.lang.String
// ... 48 elided

しかし、ラップされた場合はOption成功します:

val stringOption = Option(DummyRow().getAs[String])
// Option[String] = Some(1)

DummyRow().getAsOption[String]
// Option[String] = Some(1)

ラップされた値にアクセスしようとした場合にのみ失敗します:

stringOption.get
// java.lang.ClassCastException: java.lang.Integer cannot be cast to 
// java.lang.String
// ... 48 elided

それで、ここで何が起こりますか?制限されているように見えるClassCastExceptionので、型消去のような醜いものに関連していると思います。


*サード パーティのコードの動作を模倣するためAnyasInstanceOf存在するので、それについて詳しく説明しないでください。

** Scala 2.10.5、2.11.7 でテスト済み

*** コンテキストに興味がある場合は、Using contains in scala - exception を参照してください。

**** コメントにリンクされているその他の関連する質問:

4

2 に答える 2

9

以下は、問題の簡略化されたバージョンであり、追加のケースがありますAny

def getAs[T] = (1:Int).asInstanceOf[T]

//blows up
getAs[String]

//blows up
def p(s:String): Unit = {}
p(getAs[String])

//works
def p[T](s:T): Unit = {}
p(getAs[String])

//works
def p(s:Any): Unit = {}
p(getAs[String])

ジェネリック パラメーターを使用してメソッドを作成するため、ランタイムは気にしないため、値に「触れる」必要はありません。Generic は、実行時にAny/として扱われます。Object

于 2016-03-21T18:50:56.053 に答える