Jika saya mencoba untuk melemparkan String
ke java.util.Date
, kompiler Java menangkap kesalahan. Jadi mengapa kompiler tidak menandai yang berikut sebagai kesalahan?
List<String> strList = new ArrayList<>();
Date d = (Date) strList;
Tentu saja, JVM melempar ClassCastException
pada saat runtime, tetapi kompiler tidak menandainya.
Perilaku ini sama dengan javac 1.8.0_212 dan 11.0.2.
java
casting
compiler-errors
javac
Mike Woinoski
sumber
sumber
List
sini.Date d = (Date) new Object();
strList
itu adalah instance dari kelas yang mengimplementasikan List.Jawaban:
Para pemainnya adalah teknis memungkinkan. Tidak dapat dengan mudah dibuktikan oleh javac bahwa tidak demikian halnya dengan Anda dan JLS benar-benar mendefinisikan ini sebagai program Java yang valid, sehingga menandai kesalahan akan salah.
Ini karena
List
antarmuka. Jadi Anda bisa memiliki subclass dariDate
yang benar-benar mengimplementasikan yangList
disamarkan seperti diList
sini - dan kemudian casting ituDate
akan baik-baik saja. Sebagai contoh:Lalu:
Mendeteksi skenario semacam itu mungkin tidak selalu memungkinkan, karena akan memerlukan informasi runtime jika instance berasal dari, misalnya, suatu metode. Dan bahkan jika, itu akan membutuhkan lebih banyak upaya untuk kompiler. Kompilator hanya mencegah gips yang benar-benar tidak mungkin karena tidak ada cara bagi pohon kelas untuk mencocokkan sama sekali. Yang tidak terjadi di sini, seperti yang terlihat.
Perhatikan bahwa JLS mengharuskan kode Anda menjadi program Java yang valid. Dalam 5.1.6.1. Konversi Referensi Sempit yang Diperbolehkan dikatakan:
Jadi, bahkan jika kompiler dapat mengetahui bahwa case Anda sebenarnya tidak mungkin terbukti, ia tidak diperbolehkan menandai kesalahan karena JLS mendefinisikannya sebagai program Java yang valid.
Itu hanya akan diizinkan untuk menunjukkan peringatan.
sumber
myDate = (Date) myString
gagal. Menggunakan terminologi JLS, pernyataan berusaha untuk mengkonversi dariS
(theString
) keT
(theDate
). Di sini,S
bukan tipe antarmuka, jadi kondisi JLS yang dikutip di atas tidak berlaku. Sebagai contoh, coba casting Kalender ke Tanggal dan Anda akan mendapatkan kesalahan kompilator meskipun kelas tidak final.Date & List
dapat dihuni , itu tidak cukup untuk membuktikan bahwa itu tidak berpenghuni saat ini (mungkin di masa depan).Biarkan kami mempertimbangkan generalisasi contoh Anda:
Ini adalah alasan utama mengapa
Date d = (Date) strList;
bukan kesalahan kompilasi.The Alasan intuitif adalah bahwa compiler tidak (pada umumnya) mengetahui jenis yang tepat dari objek dikembalikan oleh metode panggilan. Ada kemungkinan bahwa selain menjadi kelas yang mengimplementasikan
List
, itu juga merupakan subkelas dariDate
.The alasan teknis adalah bahwa Java Language Specification "memungkinkan" yang konversi referensi penyempitan yang sesuai dengan jenis cor ini. Menurut JLS 5.1.6.1 :
Di tempat yang berbeda, JLS juga mengatakan bahwa pengecualian dapat dilempar saat runtime ...
Perhatikan bahwa penentuan JLS 5.1.6.1 hanya didasarkan pada tipe variabel yang dideklarasikan yang terlibat daripada tipe runtime yang sebenarnya. Dalam kasus umum, kompiler tidak dan tidak bisa mengetahui tipe runtime yang sebenarnya.
Jadi, mengapa kompiler Java tidak dapat bekerja bahwa para pemain tidak akan bekerja?
Dalam contoh saya,
someMethod
panggilan dapat mengembalikan objek dengan berbagai jenis. Bahkan jika kompiler dapat menganalisis tubuh metode dan menentukan set tipe yang tepat yang dapat dikembalikan, tidak ada yang menghentikan seseorang mengubahnya untuk mengembalikan tipe yang berbeda ... setelah mengkompilasi kode yang memanggilnya. Ini adalah alasan dasar mengapa JLS 5.1.6.1 mengatakan apa yang dikatakannya.Dalam contoh Anda, kompiler pintar bisa mengetahui bahwa para pemain tidak pernah bisa berhasil. Dan diizinkan memancarkan peringatan waktu kompilasi untuk menunjukkan masalahnya.
Jadi mengapa kompiler pintar tidak diizinkan untuk mengatakan ini adalah kesalahan?
Karena JLS mengatakan bahwa ini adalah program yang valid. Titik. Setiap kompiler yang menyebut ini sebagai kesalahan tidak akan memenuhi persyaratan Java.
Juga, setiap kompiler yang menolak program Java yang JLS dan kompiler lain katakan valid, merupakan penghalang untuk portabilitas kode sumber Java.
sumber
5.5.1. Referensi Tipe Pengecoran:
List<String>
adalahS
danDate
adalahT
dalam kasus Anda.sumber