Kelas yang dimuliakan dalam bahasa Jawa


96

Beberapa kelas di Java API standar diperlakukan sedikit berbeda dari kelas lain. Saya berbicara tentang kelas-kelas yang tidak dapat diimplementasikan tanpa dukungan khusus dari compiler dan / atau JVM.

Yang saya langsung dapatkan adalah:

  • Object (jelas) seperti itu, antara lain tidak memiliki kelas super.
  • String karena bahasa memiliki dukungan khusus untuk operator +.
  • Thread karena ia memiliki metode start () ajaib ini terlepas dari kenyataan bahwa tidak ada instruksi bytecode yang "memotong" eksekusi.

Saya kira semua kelas seperti ini dalam satu atau lain cara disebutkan di JLS. Koreksi saya jika saya salah.

Ngomong-ngomong, kelas apa lagi yang ada? Apakah ada daftar lengkap "kelas yang dimuliakan" dalam bahasa Jawa?


2
Obat generik hampir pas, tetapi tidak cukup. Mereka diimplementasikan menggunakan trik kompilator, tetapi tidak diisolasi ke satu kelas.
Bill the Lizard

2
Mereka semua adalah tipe penghormatan. ;-)
starblue

1
Apakah "thread.start" ajaib? Tentunya itu hanya beberapa kode asli yang dipanggil untuk melakukan ini?
jcoder

Pikiran itu juga mengejutkanku. Mungkin JNI saja sudah cukup untuk mengimplementasikan kelas Thread. Saya kira jika saya akan mencoba melakukan ini, saya akan menggunakan beberapa api utas tingkat OS, garpu eksekusi dalam implementasi metode start (), jalankan metode run () di utas bercabang, dan kembali. Tapi kemudian utas OS saya akan terus berjalan. Akankah itu berjalan mulus bersama dengan utas yang dibuat oleh JVM? dan menghormati model memori JLS dan sebagainya?
aioobe

2
Menurut spesifikasi, satu-satunya cara untuk membuat utas adalah dari kelas Thread ( java.sun.com/docs/books/jvms/second_edition/html/… ). Tentu saja, ini bergantung pada beberapa komunikasi tingkat naitive dengan JVM, tetapi jika Anda melakukan JNI Anda sendiri, Anda mungkin memulai utas, tetapi Anda tidak akan membuat JVM memahami apa yang Anda lakukan (kunci, model memori, dll. ). Thread memiliki hak istimewa karena spesifikasi memberikan hak istimewa khusus - satu-satunya cara untuk memulai thread.
Yishai

Jawaban:


35

Ada banyak jawaban berbeda, jadi saya pikir akan berguna untuk mengumpulkan semuanya (dan menambahkan beberapa):

Kelas

  • Kelas AutoBoxing - kompiler hanya mengizinkan untuk kelas tertentu
  • Kelas - memiliki literalnya sendiri (int.class misalnya). Saya juga akan menambahkan pengetikan generiknya tanpa membuat contoh baru.
  • String - dengan kelebihan + -operator dan dukungan literal
  • Enum - satu-satunya kelas yang dapat digunakan dalam pernyataan switch (segera hak istimewa untuk diberikan ke String juga). Itu juga melakukan hal-hal lain (pembuatan metode statis otomatis, penanganan serialisasi, dll.), Tetapi itu secara teoritis dapat dilakukan dengan kode - itu hanya banyak boilerplate, dan beberapa batasan tidak dapat diterapkan di subclass (mis. special subclassing rules) tetapi apa yang tidak pernah dapat Anda capai tanpa status priviledged dari enum adalah memasukkannya ke dalam pernyataan switch.
  • Objek - akar dari semua objek (dan saya akan menambahkan metode klon dan menyelesaikannya bukanlah sesuatu yang dapat Anda terapkan)
  • Referensi : WeakReference, SoftReference, PhantomReference
  • Utas - bahasa tidak memberi Anda instruksi khusus untuk memulai utas, melainkan secara ajaib menerapkannya ke metode start ().
  • Throwable - root dari semua class yang dapat bekerja dengan throw, throws, dan catch, serta pemahaman compiler tentang Exception vs. RuntimeException dan Error.
  • NullPointerException dan pengecualian lain seperti ArrayIndexOutOfBounds yang dapat ditampilkan oleh instruksi bytecode lain selain di depan.

Antarmuka

  • Iterable - satu-satunya antarmuka yang dapat digunakan dalam for loop yang disempurnakan

Sebutan terhormat ditujukan ke:

  • java.lang.reflect. Array - membuat array baru seperti yang didefinisikan oleh objek Kelas tidak mungkin dilakukan.
  • Anotasi Mereka adalah fitur bahasa khusus yang berperilaku seperti antarmuka pada waktu proses. Anda pasti tidak dapat menentukan antarmuka Anotasi lain, sama seperti Anda tidak dapat menentukan pengganti Object. Namun, Anda dapat menerapkan semua fungsinya dan hanya memiliki cara lain untuk mengambilnya (dan sejumlah boilerplate) daripada refleksi. Faktanya, ada banyak implementasi berbasis XML dan tag javadoc sebelum anotasi diperkenalkan.
  • ClassLoader - ini pasti memiliki hubungan istimewa dengan JVM karena tidak ada cara bahasa untuk memuat kelas, meskipun ada cara bytecode, jadi seperti Array dengan cara itu. Ia juga memiliki hak istimewa untuk dipanggil kembali oleh JVM, meskipun itu adalah detail implementasi.
  • Dapat diserialkan - Anda dapat mengimplementasikan fungsionalitas melalui refleksi, tetapi memiliki kata kunci istimewa sendiri dan Anda akan menghabiskan banyak waktu untuk akrab dengan SecurityManager dalam beberapa skenario.

Catatan: Saya meninggalkan daftar hal-hal yang menyediakan JNI (seperti IO) karena Anda selalu dapat mengimplementasikan panggilan JNI Anda sendiri jika Anda mau. Namun, panggilan asli yang berinteraksi dengan JVM dengan cara istimewa berbeda.

Array masih bisa diperdebatkan - mereka mewarisi Object, memiliki hierarki yang dipahami (Object [] adalah supertipe String []), tetapi mereka adalah fitur bahasa, bukan kelas yang ditentukan sendiri.


@Donal, sangat benar, saya sedang memikirkan anotasi runtime, tetapi anotasi tingkat sumber memang dilakukan seperti itu (xdoclet paling menonjol, atau bahkan di inti java dengan @deprecated)
Yishai

Saya baru saja berjuang melalui sekumpulan kode yang awalnya ditulis dengan pemrosesan xdoclet dan kemudian diubah menjadi anotasi. Oh, betapa saya lebih suka anotasi daripada itu (meskipun, dengan mantra maven yang sesuai, efek bersihnya sama).
Donal Fellows

@ KK_07k11A0585, Koleksi adalah api standar yang dapat dibuat oleh siapa saja dengan cara yang berbeda (sebenarnya ada implementasi alternatif yang diarahkan pada primitif, serta proyek Google yang sangat terkenal yang menyempurnakannya). Satu-satunya hal yang mereka dapatkan yang istimewa adalah Iterable, yang disebutkan dalam jawaban. Mereka adalah roti dan mentega dari pemrograman java, pastinya, tetapi mereka hanya kelas biasa, tanpa hak khusus.
Yishai

@Yishai Saat mengembangkan aplikasi apa pun, hal utama yang terpenting adalah MANAJEMEN DATA. Kita semua dapat melakukan tugas dengan berbagai cara, tetapi cara yang dioptimalkan adalah yang menggunakan lebih sedikit memori dan yang memiliki lebih sedikit penggunaan referensi yang tidak perlu. Dengan menggunakan Koleksi, kita dapat mengurutkan, mencari, dan membandingkan data dalam jumlah besar, yang menyediakan algoritme yang telah ditentukan sebelumnya seperti Pencarian Biner, Pengurutan Gabung, dll. Ini juga memberi kita Pembanding dan Antarmuka yang Dapat Dibandingkan untuk menyesuaikan teknik kita. Kelas koleksi mungkin bukan kelas terbaik di java, tapi tidak diragukan lagi merupakan kelas dengan kualitas yang dimuliakan.
KK_07k11A0585

1
Tentang apa SecurityManager? Atau apapun yang berhubungan dengan refleksi atau serialisasi?
Antimony

19

Class, tentu saja. Ini memiliki literalnya sendiri (perbedaan yang sama String, BTW) dan merupakan titik awal dari semua keajaiban refleksi itu.


Ah, poin yang bagus. Jadi apa contoh kelas literal? Apakah Anda mengacu pada MyClass.class?
aioobe

4
@aioobe: tepatnya. Perhatikan bahwa Anda juga memiliki int.class, char.class, dll.
Michael Borgwardt


12
  1. Enum. Anda tidak diizinkan untuk membuat subkelasnya, tetapi kompilator bisa.
  2. Banyak hal di bawah java.util.concurrent dapat diimplementasikan tanpa dukungan JVM, tetapi akan menjadi kurang efisien.

1
Anda dapat secara anonim membuat subkelas enum (yang merupakan dasar dari pola pengunjung yang tersirat untuk nilai enum). Tapi ya, Anda tidak bisa sepenuhnya membuat subkelas enum ;-)
Thierry

11

Semua kelas Number memiliki sedikit keajaiban dalam bentuk Autoboxing .


Yang Anda maksud adalah kelas yang membungkus primitif - yang juga mencakup Boolean dan Karakter; tetapi tidak termasuk BigInteger.
emory

1
@ Memori: Benar, hanya kelas pembungkus primitif. Sayangnya itu mengecualikan BigInteger.
Bill the Lizard

10

Karena penting kelas disebutkan, saya akan menyebutkan beberapa antarmuka:

The Iterableantarmuka (sejak 1,5) - memungkinkan sebuah objek untuk berpartisipasi dalam loop foreach:

Iterable<Foo> iterable = ...;
for (Foo foo : iterable) {

}

The Serializableantarmuka memiliki makna yang sangat khusus, yang berbeda dari antarmuka standar. Anda dapat menentukan metode yang akan dipertimbangkan meskipun tidak ditentukan dalam antarmuka (seperti readResolve()). Kata transientkunci adalah elemen bahasa yang mempengaruhi perilaku Serializablepelaksana.


Benar, Mereka adalah antarmuka, jadi mereka tidak memerlukan implementasi "khusus" per lihat. (Mirip dengan Throwable.)
aioobe

Serializable sebenarnya membutuhkan implementasi khusus. Ini adalah antarmuka yang Anda harapkan memiliki dua metode (saya lupa nama ... saya bisa google itu ...) tetapi mereka tidak diperlukan atau didefinisikan dalam skema antarmuka standar.
corsiKa

@glowcoder: bagaimanapun, pernah bisa membantah bahwa semua keistimewaan Serializable tidak relevan dengan bahasa Java, hanya untuk implementasi ObjectOutputStream dan ObjectInputStream.
Michael Borgwardt

5
@Michael Borgwardt memiliki - transientkata kunci
Bozho

1
Saya tidak berpikir begitu - Comparabletidak mengambil bagian dalam hal internal. Anda dapat dengan mudah menulis NewComparabledan baru NewArrays.sort(..)dengan fungsi yang sama
Bozho

6
  1. Throwable , RuntimeException, Error AssertionError
  2. Referensi WeakReference, SoftReference, PhantomReference
  3. Enum
  4. Anotasi

Daftar yang bagus. +1, Anotasi adalah antarmuka, dan tidak memiliki implementasi.
aioobe

1
Anotasi diperlakukan berbeda oleh kompilator daripada antarmuka normal. Mirip dengan enum, mereka semua memperluas Annotation, dan kompilator melakukannya secara otomatis. Dari JavaDoc Annotation: Antarmuka umum yang diperluas oleh semua jenis anotasi. Perhatikan bahwa antarmuka yang memperluas yang satu ini secara manual tidak menentukan jenis anotasi. Perhatikan juga bahwa antarmuka ini sendiri tidak menentukan jenis anotasi. Jadi Anda tidak dapat membuat anotasi menggunakan sintaks normal, mereka perlu mengubah kompilator untuk menambahkannya.
Andrei Fierbinteanu



2

Tidak yakin tentang ini. Tapi saya tidak bisa memikirkan cara untuk mengimplementasikan objek IO secara manual.


Anda benar, mereka tidak dapat diterapkan di Java murni. Mereka perlu diimplementasikan melalui JNI (sama seperti kelas lain yang perlu melakukan panggilan sistem). Selain itu, mereka tidak membutuhkan dukungan khusus dari compiler atau jvm.
aioobe

2

Ada keajaiban di Systemkelas.

System.arraycopy adalah pengait ke kode asli

public static native void arraycopy(Object array1, int start1, 
  Object array2, int start2, int length);

tapi...

/**
 * Private version of the arraycopy method used by the jit
 * for reference arraycopies
 */
private static void arraycopy(Object[] A1, int offset1,
  Object[] A2, int offset2, int length) {
   ...
}

1
Heys apa yang Anda maksud dengan bagian kedua dari jawaban Anda?
Pacerier

1

Nah sejak penanganan khusus menegaskan telah disebutkan. Berikut adalah beberapa jenis Exception yang memiliki perlakuan khusus oleh jvm:

  • NullPointerException
  • ArithmeticException.
  • StackOverflowException
  • Semua jenis OutOfMemoryErrors
  • ...

Pengecualian tidak khusus, tetapi jvm menggunakannya dalam kasus khusus, jadi Anda tidak dapat mengimplementasikannya sendiri tanpa menulis jvm Anda sendiri. Saya yakin ada lebih banyak pengecualian khusus.


0

Sebagian besar kelas tersebut tidak benar-benar diimplementasikan dengan bantuan 'khusus' dari kompilator atau JVM. Object memang mendaftarkan beberapa native yang melihat-lihat struktur internal JVM, tetapi Anda juga dapat melakukannya untuk class Anda sendiri. (Saya akui ini tunduk pada semantik, "panggilan asli yang ditentukan dalam JVM" dapat dianggap sebagai dukungan JVM khusus.)

Apa / itu / khusus adalah perilaku dari instruksi 'baru', dan 'lempar' dalam cara mereka menginisialisasi struktur internal ini.

Anotasi dan angka cukup aneh.


4
aioobe merujuk ke kelas yang tidak dapat Anda implementasikan sendiri, karena kelas tersebut memiliki dukungan build khusus. Anda tidak dapat membuat kelas Object Anda sendiri sebagai root dari sistem tipe tanpa mewarisi bentuk java.lang.Object. Objek memiliki dukungan khusus baik dari kompilator maupun jvm untuk memastikannya adalah kelas root. Panggilan asli tidak cukup untuk menyiasati ini.
josefx
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.