Apa hubungan antara Any, AnyVal, AnyRef, Object dan bagaimana mereka memetakannya saat digunakan dalam kode Java?

111

Saya biasanya akhirnya mencoba setiap kombinasi sampai terkompilasi. Adakah yang bisa menjelaskan apa yang harus saya gunakan di mana?

huynhjl
sumber

Jawaban:

125

Saya tidak akan setuju dengan jawaban Chris dalam satu hal. Kelas-kelas , dan yang kelas. Tapi mereka tidak muncul sebagai kelas dalam bytecode, karena keterbatasan intrinsik JVM.AnyAnyRefAnyVal

Ini muncul dari fakta bahwa tidak semua yang ada di Java adalah objek. Selain objek, ada primitif. Semua objek di Java adalah turunan dari java.lang.Object, tetapi objek primitif dipisahkan dan, saat ini * , tidak dapat dikembangkan oleh programmer. Perhatikan juga bahwa primitif memiliki "operator", bukan metode.

Di Scala, di sisi lain, semuanya adalah objek, semua objek termasuk dalam kelas, dan mereka berinteraksi melalui metode. Bytecode JVM yang dihasilkan tidak mencerminkan hal ini, tetapi itu tidak membuatnya kurang begitu, sama seperti Java yang memiliki generik, meskipun bytecode tidak memilikinya.

Jadi, di Scala, semua objek adalah turunan dari Any, dan itu termasuk apa yang dianggap Java sebagai objek dan apa yang dianggap primitif oleh Java. Tidak ada padanan di Jawa karena tidak ada penyatuan seperti itu.

Segala sesuatu yang dianggap primitif di Jawa adalah turunan dari AnyValScala. Hingga Scala 2.10.0, AnyValditutup, dan pemrogram tidak dapat memperpanjangnya. Menarik untuk melihat apa yang akan terjadi dengan Scala di .Net, karena interoperabilitas saja membutuhkan Scala untuk setidaknya mengenali "primitif" yang ditentukan pengguna.

Juga memperluas Anyadalah AnyRef, yang setara dengan java.lang.Object(pada JVM pada setiap tingkat).

Sampai Scala 2.9.x, pengguna tidak bisa memperpanjang Anyatau AnyVal, atau referensi mereka dari Jawa, tapi ada yang kegunaan lain mereka bisa dihukum di Scala. Secara khusus, ketik tanda tangan:

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

Arti masing-masing harus jelas dari hierarki kelas. Catatan, bagaimanapun, adalah itu fdan hakan auto-box, tapi gtidak akan. Itu sedikit kebalikan dari apa yang dilakukan Java, dalam hal itu fdan htidak dapat ditentukan, dan g(didefinisikan dengan java.lang.Object) akan menyebabkan auto-boxing.

Dimulai dengan Scala 2.10.0, pengguna dapat memperluas AnyValatau Any, dengan semantik berikut:

  • Jika sebuah kelas diperluas AnyVal, tidak ada instance yang akan dibuat untuknya di heap dalam kondisi tertentu. Ini berarti bidang dari kelas ini (pada 2.10.0 hanya satu bidang yang diizinkan - apakah itu akan berubah masih harus dilihat) akan tetap berada di tumpukan, apakah itu primitif atau referensi ke objek lain. Ini memungkinkan metode ekstensi tanpa biaya pembuatan contoh.

  • Jika suatu sifat meluas Any, maka sifat itu bisa digunakan dengan kelas yang diperluas AnyRefdan kelas yang diperluas AnyVal.

PS: Dalam pandangan saya sendiri, Java kemungkinan akan mengikuti C # dalam mengizinkan "struct" primitif, dan mungkin typedefs, karena paralelisme tanpa menggunakan mereka terbukti sulit dicapai dengan kinerja yang baik.

Daniel C. Sobral
sumber
2
Pembaruan: pada Scala 2.9.2, AnyValdidefinisikan sebagai sealed trait AnyVal extends Any. Namun dalam Scala 2.10 ini telah berubah menjadi abstract class AnyVal extends Any with NotNull, dan sekarang mungkin untuk memperpanjang AnyValdengan fitur kelas nilai baru, misalnya: class MyValue(val u: Int) extends AnyVal.
ebruchez
@ebruchez Terima kasih atas catatannya. Saya telah memperbarui jawaban saya dengan gambaran umum tentang kemampuan baru.
Daniel C. Sobral
Bagaimana Nothing dan Null berhubungan dengan ini?
Gaurav Khare
5

Anydan AnyVal, saya percaya, adalah bagian dari sistem tipe scala dan bukan kelas seperti itu (dengan cara yang sama yaitu Nothingtipe, bukan kelas). Anda tidak dapat menggunakannya secara eksplisit dari dalam kode Java.

Namun, dalam interoperasi Java / Scala, metode yang menerima Java Objectakan mengharapkan scala Any/ AnyRef.

Apa yang sebenarnya Anda coba lakukan?

oxbow_lakes
sumber
Saya mencoba memahami topik ini dengan lebih baik sehingga saya tahu tipe apa yang harus saya gunakan ketika saya berencana menggunakan Java call Scala atau sebaliknya. Jawaban stackoverflow.com/questions/2334200/… ini dan pemerannya AnyRefhanya mengingatkan saya bahwa ini masih misterius bagi saya.
huynhjl