Pertama-tama, kita hanya berbicara tentang variabel lokal . Final yang efektif tidak berlaku untuk bidang. Ini penting, karena semantik untuk finalbidang sangat berbeda dan tunduk pada pengoptimalan kompiler berat dan janji model memori, lihat $ 17.5.1 tentang semantik bidang akhir.
Di tingkat permukaan finaldan effectively finaluntuk variabel lokal memang identik. Namun, JLS membuat perbedaan yang jelas antara keduanya yang sebenarnya memiliki berbagai macam efek dalam situasi khusus seperti ini.
Premis
Dari JLS§4.12.4 tentang finalvariabel:
Sebuah variabel konstan adalah finalvariabel tipe primitif atau tipe String yang diinisialisasi dengan ekspresi konstan ( §15.29 ). Apakah suatu variabel adalah variabel konstan atau tidak, mungkin memiliki implikasi sehubungan dengan inisialisasi kelas ( §12.4.1 ), kompatibilitas biner ( §13.1 ), keterjangkauan ( §14.22 ), dan penugasan yang pasti ( §16.1.1 ).
Karena intprimitif, variabelnya aadalah variabel konstan .
Selanjutnya dari bab yang sama tentang effectively final:
Variabel tertentu yang tidak dinyatakan final malah dianggap final secara efektif: ...
Jadi dari cara ini bernada, jelas bahwa dalam contoh lain, ayang tidak dianggap sebagai variabel konstan, karena belum final , tetapi hanya efektif akhir.
Tingkah laku
Sekarang kita memiliki perbedaan, mari kita cari apa yang terjadi dan mengapa keluarannya berbeda.
Anda menggunakan operator bersyarat di ? :sini, jadi kita harus memeriksa definisinya. Dari JLS§15.25 :
Ada tiga jenis ekspresi kondisional, diklasifikasikan menurut ekspresi operan kedua dan ketiga: ekspresi bersyarat boolean , ekspresi bersyarat numerik , dan ekspresi bersyarat referensi .
Dalam hal ini, kita berbicara tentang ekspresi kondisional numerik , dari JLS§15.25.2 :
Jenis ekspresi bersyarat numerik ditentukan sebagai berikut:
Dan itu adalah bagian di mana kedua kasus diklasifikasikan secara berbeda.
efektif akhir
Versi yang effectively finalcocok dengan aturan ini:
Jika tidak, promosi numerik umum ( §5.6 ) diterapkan ke operan kedua dan ketiga, dan jenis ekspresi kondisional adalah jenis yang dipromosikan dari operan kedua dan ketiga.
Yang merupakan perilaku yang sama seperti yang akan Anda lakukan 5 + 'd', yaitu int + char, yang menghasilkan int. Lihat JLS§5.6
Promosi numerik menentukan jenis yang dipromosikan dari semua ekspresi dalam konteks numerik. Jenis yang dipromosikan dipilih sedemikian rupa sehingga setiap ekspresi dapat dikonversi ke jenis yang dipromosikan, dan, dalam kasus operasi aritmatika, operasi tersebut ditentukan untuk nilai dari jenis yang dipromosikan. Urutan ekspresi dalam konteks numerik tidak signifikan untuk promosi numerik. Aturannya adalah sebagai berikut:
[...]
Selanjutnya, konversi primitif pelebaran ( §5.1.2 ) dan konversi primitif mempersempit ( §5.1.3 ) diterapkan ke beberapa ekspresi, menurut aturan berikut:
Dalam konteks pilihan numerik, aturan berikut berlaku:
Jika ada ekspresi berjenis intdan bukan merupakan ekspresi konstan ( §15.29 ), maka jenis yang dipromosikan adalah int, dan ekspresi lain yang bukan berjenis intmenjalani konversi primitif yang melebar menjadi int.
Jadi semuanya dipromosikan menjadi intapa aadanya int. Itu menjelaskan keluaran dari 97.
terakhir
Versi dengan finalvariabel cocok dengan aturan ini:
Jika salah satu operan bertipe Twhere Tis byte,, shortor char, dan operand lainnya adalah ekspresi konstan ( §15.29 ) dari tipe intyang nilainya dapat direpresentasikan dalam tipeT , maka tipe ekspresi kondisionalnya adalah T.
Variabel terakhir aadalah tipe intdan ekspresi konstan (karena memang demikian final). Ini dapat direpresentasikan sebagai char, maka hasilnya adalah tipe char. Itu menyimpulkan hasilnyaa .
Contoh string
Contoh persamaan string didasarkan pada perbedaan inti yang sama, finalvariabel diperlakukan sebagai ekspresi / variabel konstan, daneffectively final tidak.
Di Java, string interning didasarkan pada ekspresi konstan
"a" + "b" + "c" == "abc"
adalah true juga (tidak menggunakan konstruksi ini dalam kode nyata).
Lihat JLS§3.10.5 :
Selain itu, literal string selalu mengacu pada instance kelas String yang sama. Ini karena string literal - atau, lebih umum , string yang merupakan nilai ekspresi konstan ( §15.29 ) - " disimpan " sehingga dapat berbagi instance unik, menggunakan metode String.intern( §12.5 ).
Mudah untuk dilupakan karena ini terutama berbicara tentang literal, tetapi sebenarnya juga berlaku untuk ekspresi konstan.