Any、AnyVal、AnyRef、Objectの関係は何ですか?また、Javaコードで使用する場合、それらはどのようにマッピングされますか?


111

私は通常、コンパイルされるまですべての組み合わせを試します。誰かがどこで何を使うべきか説明できますか?

回答:


125

ある意味で、クリスの 答えには同意しません。クラスAnyAnyRefそしてAnyVal あるクラス。ただし、JVMの本質的な制限のため、バイトコードではクラスとして表示されません。

これは、Javaのすべてがオブジェクトではないという事実から生じます。オブジェクトに加えて、プリミティブがあります。Javaのすべてのオブジェクトはの子孫ですがjava.lang.Object、プリミティブは別々に設定されており、現時点では*であり、プログラマは拡張できません。また、プリミティブにはメソッドではなく「演算子」があることに注意してください。

一方、Scalaでは、すべてオブジェクトであり、すべてのオブジェクトはクラスに属し、メソッドを介して相互作用します。生成されたJVMバイトコードはこれを反映していませんが、バイトコードにジェネリックが含まれていない場合でも、Javaにジェネリックが含まれているのと同じように、JVMバイトコードにはそれが反映されています。

したがって、Scalaでは、すべてのオブジェクトはの子孫でありAny、Javaがオブジェクトと見なすものとJavaがプリミティブと見なすものの両方が含まれます。そのような統一がないため、Javaには同等のものはありません。

Javaでプリミティブと見なされるものはすべてAnyVal、Scalaの子孫です。Scala 2.10.0までAnyValは封印され、プログラマはそれを拡張できませんでした。相互運用性だけでScalaは少なくともユーザー定義の「プリミティブ」を認識する必要があるため、.Net上のScalaで何が起こるかを見るのは興味深いはずです。

また、拡張AnyAnyRefに相当しますjava.lang.Object(これは、とにかくJVM上で)。

Scala 2.9.xまでは、ユーザーはJavaからそれらを拡張しAnyたりAnyVal、参照したりすることはできませんでしたが、Scalaで使用できる他の用途がありました。具体的には、型シグネチャ:

def f(x: AnyVal) = println(x)
def g(x: AnyRef) = println(x)
def h(x: Any) = println(x)

それぞれの意味は、クラス階層から明らかです。注目すべきは、しかし、それであるfh意志オートボックスが、gしません。これはJavaのことで、何の反対のビットであるfh指定することはできません、とg(で定義されたjava.lang.Objectオートボクシングを引き起こす)を。

ただし、Scala 2.10.0以降では、ユーザーは次のセマンティクスでAnyValorまたはを拡張できAnyます。

  • クラスがextendsの場合、AnyVal特定の条件下では、そのクラスのインスタンスはヒープ上に作成されません。これは、このクラスのフィールド(2.10.0では、単一のフィールドのみが許可されます-変更が見られるかどうかにかかわらず)は、プリミティブであっても、他のオブジェクトへの参照であっても、スタックにとどまります。これにより、インスタンス化のコストなしに拡張メソッドを使用できます。

  • 形質が拡張する場合Any、それは両方拡張するクラスで使用することができるAnyRefと拡張するクラスAnyVal

PS:私の見解では、JavaはC#に従って「struct」プリミティブを許可する可能性が高く、typedefを使用する可能性があります。これは、それらに頼らずに並列処理を行うと、優れたパフォーマンスで達成することが困難になるためです。


2
更新:Scala 2.9.2以降、AnyValとして定義されていsealed trait AnyVal extends Anyます。しかし、Scala 2.10ではこれがに変更されabstract class AnyVal extends Any with NotNullAnyVal新しい値クラス機能で拡張できるようになりましたclass MyValue(val u: Int) extends AnyVal。例:。
ebruchez 2012

@ebruchezメモをありがとう。新しい機能の概要で回答を更新しました。
ダニエルC.ソブラル

Nothing and Nullはこれとどのように関係していますか?
Gaurav Khare


5

Anyそして、AnyValされ、Iは、Scalaの一部と信じ型システムのようなクラスではない(同様にNothingタイプしないクラスです)。Javaコード内から明示的に使用することはできません。

ただし、Java / Scalaの相互運用では、Javaを受け入れるメソッドObjectはscala Any/ を期待しAnyRefます。

実際に何をしようとしていますか?


私はこのトピックをよりよく理解しようとしています。これにより、JavaからScalaを呼び出すことを計画しているとき、またはその逆を計画しているときに使用する必要がある型がわかります。この回答stackoverflow.com/questions/2334200/…とそのキャストAnyRefは、これがまだ私には不思議であることを思い出させてくれました。
huynhjl
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.