1. ホーム
  2. scala

[解決済み] Any、AnyVal、AnyRef、Objectの関係と、Javaコードでのマッピングについて教えてください。

2022-09-23 22:57:13

質問

私は通常、コンパイルできるまであらゆる組み合わせを試してしまいます。どなたか、どこに何を使うべきか説明していただけませんか?

どのように解決するのですか?

に反対します。 クリスの 答え の一点です。クラスは Any , AnyRefAnyVal クラスです。しかし、JVMの本質的な制限のために、それらはバイトコードでクラスとして現れません。

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

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

ですから、Scalaでは、全てのオブジェクトは Any の子孫であり,Javaがオブジェクトとみなすものと,Javaがプリミティブとみなすものの両方が含まれます.Javaにはそのような統一がないので、同等のものはありません。

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

また AnyAnyRef と等価である。 java.lang.Object と同じです(JVM上ではともかく)。

Scala 2.9.x までは、ユーザは Any または AnyVal であり、Javaからそれらを参照することもできませんが、そこに がありました。 は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 からは、ユーザは AnyVal または Any のように、以下のようなセマンティクスを持つ。

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

  • もしtraitが Any を拡張している場合、そのクラスは AnyRef .

PS: 私自身の見解では、Java は C# に続いて "struct" プリミティブ、そしておそらく typedefs を許可するようになると思われますが、それらに頼らない並列処理を良いパフォーマンスで達成することが困難であることが判明しているからです。