36

テストとして、私はこのコードを書きました:

object Ambig extends App {
  def f( x:Int    ) { println("Int"   ) }
  def f( x:String ) { println("String") }
  f( null.asInstanceOf[Int   ] )
  f( null.asInstanceOf[String] )
  f(null)
}

f()の最後の呼び出しで、あいまいであるというエラーが発生することを期待していました。コンパイラーはそれを受け入れ、次の出力を生成しました。

Int
String
String

これは、IntがAnyRefではないという事実に関係していると推測しているので、f(null)で機能するfのバージョンはf(x:String)のみです。しかし、Intをnullにできない場合、null.asInstanceOf [Int]はどういう意味ですか?担当者は、それがInt型であると言っています。

scala> :type null.asInstanceOf[Int]
Int

しかし、それがどのように機能するのかはよくわかりません。結局のところ、文字列をIntにキャストしようとすると、すべての地獄が解き放たれます。

scala> "foo".asInstanceOf[Int]
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source)
        ...

もちろん、それは当然のことです。「foo」をIntにすることはできません。しかし、どちらもnullにできないので、なぜintにnullをキャストするのですか?おそらく何らかの形でボクシングをしていますが、型はまだIntであり、nullにすることはできません...

私は何が欠けていますか?

4

4 に答える 4

53

にキャストnullする動作はInt、それが行われるコンテキストによって異なります。

まず、aをにキャストするnullと、Int実際には、値が。であるボックス化された整数を意味しますnull。期待される型が( JVMバイトコードでは、プリミティブ型と同じ参照を持つ参照型を参照する方法がないため、舞台裏にAny変換される)コンテキストに式を配置すると、これはObject値はそれ以上変換されません-それがprintln(null.asInstanceOf[Int])印刷する理由nullです。

Intただし、プリミティブ(Java int)が期待されるコンテキストでこれと同じボックス化された整数値を使用すると、プリミティブに変換され、 null(参照型のデフォルト値として)0(プリミティブ型のデフォルト値として)変換されます。 )。

ジェネリックメソッドがこのキャストを行う場合、当然、あなたはnull戻ってきます。

ただし、このメソッドが特殊化されている場合、その戻り型はInt(この場合はプリミティブ整数)であるため、null: Any以前と同様に、値をプリミティブに変換する必要があります。

したがって、実行中:

object Test extends App {
  println(null.asInstanceOf[Int])

  def printit(x: Int) = println(x)

  printit(null.asInstanceOf[Int])

  def nullint[T] = null.asInstanceOf[T]

  println(nullint[Int])

  def nullspecint[@specialized(Int) T] = null.asInstanceOf[T]

  println(nullspecint[Int])
}

生成:

null
0
null
0
于 2012-05-25T08:09:11.703 に答える
21

これが重要ですasInstanceOf。意味をなす必要はありません。このメソッドが行うことは、コンパイラーにSENSEの作成を停止し、あなたが言っていることを信頼するように指示することです。

さて、なぜそれが0を返すのか知りたいのなら、それはでではなく、でasInstanceOf動作するからです。に適用すると、代わりにボックス化されたバージョンが使用され、ボックス化された値は0になります。AnyRefAnyValAnyValnull

于 2012-05-25T18:13:46.263 に答える
4

自動的にゼロに変換しているようです。

scala> null.asInstanceOf[Int]
res0: Int = 0

そしてもちろん、nullとは異なり、0は。にすることができますInt

于 2012-05-25T05:41:19.997 に答える
0

まず、http: //www.scala-lang.org/api/current/index.html#scala.Nullに記載されているようnullに割り当てることができないことに同意します。scala.Int

第二に、なぜ私たちがそうするときprintln(null.asInstanceOf[Int])、それは与えるのnullですか?
これは、printlnの実装によるものです。最終的にはjavaString.valueOfメソッドを呼び出します。

return (obj == null) ? "null" : obj.toString();

シェルでaを実行するnull.asInstanceOf[Int] == nullと、trueが返されますが、「 `=='を使用してInt型とNull型の値を比較すると、常にfalseが生成される」という反対の警告が表示されます。これはscalaの型消去で問題になるかもしれないと思います。

必要なのはscalaprintlnだけです。どのタイプでも、実際のキャストはnull.asInstanceOf[Int]まだ行われていません。null.asInstanceOf[Int]したがって、Intに割り当てると、Scalaの消去セマンティクスに基づいて実行時にキャストが行われ、それに0が割り当てられることを覚えておく必要があります。

ちなみに、scalaは暗黙の変換を行っているので、コンパイルエラーなしでaf(null)を実行できます

 null -> java.lang.Integer -> scala.Int

ただし、実行時に爆発することがわかります。

于 2015-09-26T18:46:15.253 に答える