Hal pertama yang perlu diingat adalah bahwa operator ternary Java memiliki "tipe", dan bahwa inilah yang akan ditentukan dan dipertimbangkan oleh kompilator apa pun tipe aktual / nyata dari parameter kedua atau ketiga. Tergantung pada beberapa faktor, tipe operator ternary ditentukan dengan cara berbeda seperti yang diilustrasikan dalam Spesifikasi Bahasa Jawa 15.26
Dalam pertanyaan di atas kita harus mempertimbangkan kasus terakhir:
Jika tidak, operan kedua dan ketiga adalah tipe S1 dan S2 masing-masing. Misalkan T1 adalah tipe yang dihasilkan dari penerapan konversi tinju ke S1 , dan biarkan T2 adalah tipe yang dihasilkan dari penerapan konversi tinju ke S2 . Jenis ekspresi kondisional adalah hasil dari penerapan konversi tangkap (§5.1.10) ke lub (T1, T2) (§15.12.2.7).
Sejauh ini, ini adalah kasus yang paling rumit setelah Anda menerapkan konversi tangkapan (§5.1.10) dan yang paling utama di lub (T1, T2) .
Dalam bahasa Inggris biasa dan setelah penyederhanaan ekstrim kita dapat menggambarkan proses sebagai penghitungan "Least Common Superclass" (ya, pikirkan LCM) dari parameter kedua dan ketiga. Ini akan memberi kita "tipe" operator ternary. Sekali lagi, apa yang baru saja saya katakan adalah penyederhanaan ekstrem (pertimbangkan kelas yang mengimplementasikan beberapa antarmuka umum).
Misalnya, jika Anda mencoba yang berikut:
long millis = System.currentTimeMillis();
return(true ? new java.sql.Timestamp(millis) : new java.sql.Time(millis));
Anda akan melihat bahwa jenis ekspresi kondisional yang dihasilkan adalah java.util.Date
"Least Common Superclass" untuk Timestamp
/ Time
pair.
Karena null
dapat diautobox ke apa pun, "Least Common Superclass" adalah Integer
kelas dan ini akan menjadi tipe kembalinya ekspresi kondisional (operator ternary) di atas. Nilai kembali kemudian akan menjadi pointer nol dari jenis Integer
dan itulah yang akan dikembalikan oleh operator ternary.
Saat runtime, ketika Java Virtual Machine membuka kotak Integer
a NullPointerException
dilemparkan. Ini terjadi karena JVM mencoba untuk memanggil fungsi null.intValue()
, di mana null
adalah hasil dari autoboxing.
Menurut pendapat saya (dan karena pendapat saya tidak ada dalam Spesifikasi Bahasa Jawa, banyak orang akan menganggapnya salah) penyusun melakukan pekerjaan yang buruk dalam mengevaluasi ekspresi dalam pertanyaan Anda. Mengingat bahwa Anda menulis true ? param1 : param2
kompiler harus segera menentukan bahwa parameter pertama - null
- akan dikembalikan dan itu akan menghasilkan kesalahan kompiler. Ini agak mirip dengan ketika Anda menulis while(true){} etc...
dan kompiler mengeluh tentang kode di bawah loop dan menandainya Unreachable Statements
.
Kasus kedua Anda cukup mudah dan jawaban ini sudah terlalu lama ...;)
KOREKSI:
Setelah analisis lain, saya percaya bahwa saya salah mengatakan bahwa suatu null
nilai dapat dikotak / diautobosisikan ke apa saja. Berbicara tentang Integer kelas, tinju eksplisit terdiri dari memanggil new Integer(...)
konstruktor atau mungkin Integer.valueOf(int i);
(saya menemukan versi ini di suatu tempat). Yang pertama akan melempar NumberFormatException
(dan ini tidak terjadi) sementara yang kedua tidak akan masuk akal karena int
tidak bisa null
...
int foo = (true ? null : 0)
dannew Integer(null)
keduanya mengkompilasi dengan baik, yang kedua adalah bentuk eksplisit dari autoboxing.