int i = (int) Object baru (); mengkompilasi dengan baik.
Sachin Verma
Jawaban:
243
Generik di Jawa sepenuhnya merupakan konstruksi waktu kompilasi - kompiler mengubah semua penggunaan umum menjadi gips ke tipe yang tepat. Ini untuk menjaga kompatibilitas ke belakang dengan runtime JVM sebelumnya.
Ini:
List<ClassA> list =newArrayList<ClassA>();
list.add(newClassA());ClassA a = list.get(0);
diubah menjadi (kurang-lebih):
List list =newArrayList();
list.add(newClassA());ClassA a =(ClassA)list.get(0);
Jadi, apa pun yang digunakan sebagai obat generik harus dapat dikonversi ke Object (dalam contoh ini get(0)mengembalikan sebuah Object), dan tipe primitif tidak. Jadi mereka tidak dapat digunakan dalam obat generik.
@DanyalAytekin - Bahkan, Java generics TIDAK ditangani seperti template C ++ sama sekali ...
Stephen C
20
Mengapa kompiler Java juga tidak bisa mengetikkan tipe primitif sebelum digunakan? Ini harusnya benar kan?
vrwim
13
@vrwim - Mungkin saja. Tapi itu hanya gula sintaksis. Masalah sebenarnya adalah bahwa generik Java dengan primitif kotak relatif mahal baik dalam waktu maupun ruang dibandingkan dengan model C ++ / C # ... di mana tipe primitif sebenarnya digunakan.
Stephen C
6
@ MauganRa ya saya tahu saya bisa :) Saya berdiri di tanah saya bahwa ini adalah desain yang mengerikan tho. Mudah-mudahan itu akan diperbaiki di java 10 (atau jadi saya dengar) dan juga fungsi urutan yang lebih tinggi. Jangan mengutip saya pada itu.
Ced
4
@Ced sepenuhnya setuju bahwa itu adalah desain buruk yang tanpa henti menyakiti pemula maupun profesional
MauganRa
37
Di Jawa, obat generik bekerja dengan cara yang mereka lakukan ... setidaknya sebagian ... karena mereka ditambahkan ke bahasa beberapa tahun setelah bahasa dirancang 1 . Para perancang bahasa dibatasi dalam pilihan mereka untuk obat generik dengan harus datang dengan desain yang kompatibel dengan bahasa yang ada dan perpustakaan kelas Java .
Bahasa pemrograman lain (misalnya C ++, C #, Ada) memungkinkan tipe primitif digunakan sebagai tipe parameter untuk generik. Tetapi sisi lain dari melakukan ini adalah bahwa implementasi generik bahasa (atau tipe templat) bahasa tersebut biasanya memerlukan pembuatan salinan berbeda dari tipe generik untuk setiap parameterisasi jenis.
1 - Alasan mengapa obat generik tidak dimasukkan dalam Java 1.0 adalah karena tekanan waktu. Mereka merasa bahwa mereka harus merilis bahasa Jawa dengan cepat untuk mengisi peluang pasar baru yang disajikan oleh browser web. James Gosling telah menyatakan bahwa dia ingin memasukkan obat generik jika mereka punya waktu. Akan seperti apa bahasa Jawa jika ini terjadi adalah dugaan siapa pun.
Dalam java generik diimplementasikan dengan menggunakan "Type erasure" untuk kompatibilitas. Semua tipe generik dikonversi ke Object pada saat runtime. sebagai contoh,
publicclassContainer<T>{private T data;public T getData(){return data;}}
Saya pikir pertanyaannya di sini adalah "mengapa". Mengapa obat generik memerlukan Objek? Tampaknya konsensus bahwa itu kurang dari pilihan desain dan lebih mengalah ke kompatibilitas. Di mata saya, jika obat generik tidak dapat menangani primitif, itu adalah defisit fungsionalitas. Seperti berdiri, segala sesuatu yang melibatkan primitif harus ditulis untuk setiap primitif: alih-alih Pembanding <t, t>, kita memiliki Integer.compare (int a, int b), Byte.compare (byte a, byte b), dll. Itu bukan solusi!
John P
1
Ya generik lebih dari tipe primitif adalah fitur yang harus dimiliki. Berikut ini tautan ke proposal untuk itu openjdk.java.net/jeps/218
crow
5
Sesuai Dokumentasi Java , variabel tipe generik hanya dapat dipakai dengan tipe referensi, bukan tipe primitif.
Implementasi Java saat ini terhapus yang menghasilkan satu kelas untuk semua instantiations referensi dan tidak ada dukungan untuk instantiations primitif. (Ini adalah terjemahan yang homogen, dan pembatasan bahwa generik Java hanya dapat berkisar dari tipe referensi berasal dari keterbatasan terjemahan homogen sehubungan dengan set bytecode dari JVM, yang menggunakan bytecode yang berbeda untuk operasi pada tipe referensi vs tipe primitif.) Namun, generik yang terhapus di Jawa menyediakan parametrikitas perilaku (metode generik) dan parametrik data (contoh mentah dan wildcard dari tipe generik).
...
strategi terjemahan yang homogen dipilih, di mana variabel tipe generik dihapus ke batas mereka ketika mereka dimasukkan ke dalam bytecode. Ini berarti bahwa apakah suatu kelas adalah generik atau tidak, itu masih mengkompilasi ke satu kelas, dengan nama yang sama, dan yang tanda tangan anggotanya sama. Keamanan tipe diverifikasi pada waktu kompilasi, dan runtime tidak terkekang oleh sistem tipe generik. Pada gilirannya, ini memberlakukan batasan bahwa obat generik hanya dapat bekerja di atas tipe referensi, karena Object adalah tipe yang paling umum tersedia, dan tidak meluas ke tipe primitif.
Saat membuat objek, Anda tidak bisa mengganti tipe primitif untuk parameter tipe. Mengenai alasan pembatasan ini, ini adalah masalah implementasi kompiler. Tipe primitif memiliki instruksi bytecode mereka sendiri untuk memuat dan menyimpan ke tumpukan mesin virtual. Jadi bukan tidak mungkin untuk mengkompilasi generik primitif ke dalam jalur bytecode yang terpisah ini, tetapi itu akan membuat kompiler menjadi rumit.
Jawaban:
Generik di Jawa sepenuhnya merupakan konstruksi waktu kompilasi - kompiler mengubah semua penggunaan umum menjadi gips ke tipe yang tepat. Ini untuk menjaga kompatibilitas ke belakang dengan runtime JVM sebelumnya.
Ini:
diubah menjadi (kurang-lebih):
Jadi, apa pun yang digunakan sebagai obat generik harus dapat dikonversi ke Object (dalam contoh ini
get(0)
mengembalikan sebuahObject
), dan tipe primitif tidak. Jadi mereka tidak dapat digunakan dalam obat generik.sumber
Di Jawa, obat generik bekerja dengan cara yang mereka lakukan ... setidaknya sebagian ... karena mereka ditambahkan ke bahasa beberapa tahun setelah bahasa dirancang 1 . Para perancang bahasa dibatasi dalam pilihan mereka untuk obat generik dengan harus datang dengan desain yang kompatibel dengan bahasa yang ada dan perpustakaan kelas Java .
Bahasa pemrograman lain (misalnya C ++, C #, Ada) memungkinkan tipe primitif digunakan sebagai tipe parameter untuk generik. Tetapi sisi lain dari melakukan ini adalah bahwa implementasi generik bahasa (atau tipe templat) bahasa tersebut biasanya memerlukan pembuatan salinan berbeda dari tipe generik untuk setiap parameterisasi jenis.
1 - Alasan mengapa obat generik tidak dimasukkan dalam Java 1.0 adalah karena tekanan waktu. Mereka merasa bahwa mereka harus merilis bahasa Jawa dengan cepat untuk mengisi peluang pasar baru yang disajikan oleh browser web. James Gosling telah menyatakan bahwa dia ingin memasukkan obat generik jika mereka punya waktu. Akan seperti apa bahasa Jawa jika ini terjadi adalah dugaan siapa pun.
sumber
Dalam java generik diimplementasikan dengan menggunakan "Type erasure" untuk kompatibilitas. Semua tipe generik dikonversi ke Object pada saat runtime. sebagai contoh,
akan terlihat saat runtime sebagai,
compiler bertanggung jawab untuk menyediakan gips yang tepat untuk memastikan keamanan tipe.
akan menjadi
Sekarang pertanyaannya adalah mengapa "Objek" dipilih sebagai tipe saat runtime?
FYI: Proyek Valhalla berusaha mengatasi masalah di atas.
sumber
Koleksi didefinisikan membutuhkan jenis yang berasal dari
java.lang.Object
. Tipe dasar tidak melakukan itu.sumber
Sesuai Dokumentasi Java , variabel tipe generik hanya dapat dipakai dengan tipe referensi, bukan tipe primitif.
Ini seharusnya datang di Jawa 10 di bawah Project Valhalla .
Dalam makalah Brian Goetz tentang Keadaan Spesialisasi
Ada penjelasan yang sangat baik tentang alasan yang generik tidak didukung untuk primitif. Dan, bagaimana itu akan diimplementasikan dalam rilis Java di masa depan.
...
sumber
Saat membuat objek, Anda tidak bisa mengganti tipe primitif untuk parameter tipe. Mengenai alasan pembatasan ini, ini adalah masalah implementasi kompiler. Tipe primitif memiliki instruksi bytecode mereka sendiri untuk memuat dan menyimpan ke tumpukan mesin virtual. Jadi bukan tidak mungkin untuk mengkompilasi generik primitif ke dalam jalur bytecode yang terpisah ini, tetapi itu akan membuat kompiler menjadi rumit.
sumber