Di Jawa kami menggunakan final
kata kunci dengan variabel untuk menentukan nilainya tidak boleh diubah. Tetapi saya melihat bahwa Anda dapat mengubah nilai dalam konstruktor / metode kelas. Sekali lagi, jika variabelnya static
maka itu adalah kesalahan kompilasi.
Ini kodenya:
import java.util.ArrayList;
import java.util.List;
class Test {
private final List foo;
public Test()
{
foo = new ArrayList();
foo.add("foo"); // Modification-1
}
public static void main(String[] args)
{
Test t = new Test();
t.foo.add("bar"); // Modification-2
System.out.println("print - " + t.foo);
}
}
Kode di atas berfungsi dengan baik dan tidak ada kesalahan.
Sekarang ubah variabel sebagai static
:
private static final List foo;
Sekarang ini adalah kesalahan kompilasi. Bagaimana cara final
kerjanya?
Jawaban:
Anda selalu diizinkan untuk menginisialisasi sebuah
final
variabel. Kompiler memastikan bahwa Anda hanya dapat melakukannya sekali.Perhatikan bahwa metode pemanggilan pada objek yang disimpan dalam
final
variabel tidak ada hubungannya dengan semantikfinal
. Dengan kata lain:final
hanya tentang referensi itu sendiri, dan bukan tentang isi objek yang direferensikan.Java tidak memiliki konsep kekekalan objek; ini dicapai dengan hati-hati merancang objek, dan merupakan upaya yang jauh dari sepele.
sumber
final
. Objek yang bisa berubah juga dapat dialokasikan secara stack.final
bidang mungkin membantu analisis pelarian, tapi itu rute yang tidak langsung. Juga perhatikan bahwa variabel akhir yang efektif memiliki perlakuan yang sama seperti yang ditandaifinal
dalam kode sumber.final
hadir dalam file kelas dan memiliki konsekuensi semantik yang signifikan untuk mengoptimalkan runtime. Mungkin juga menimbulkan biaya karena JLS memiliki jaminan kuat tentang konsistensifinal
bidang suatu objek. Sebagai contoh, prosesor ARM harus menggunakan instruksi penghalang memori eksplisit pada akhir setiap konstruktor dari kelas yang memilikifinal
bidang. Pada prosesor lain, ini tidak diperlukan.Ini pertanyaan wawancara favorit . Dengan pertanyaan ini, pewawancara mencoba untuk mengetahui seberapa baik Anda memahami perilaku objek sehubungan dengan konstruktor, metode, variabel kelas (variabel statis) dan variabel instan.
Dalam kasus di atas, kami telah mendefinisikan konstruktor untuk 'Tes' dan memberinya metode 'setFoo'.
Tentang konstruktor: Konstruktor dapat dipanggil hanya satu kali per pembuatan objek dengan menggunakan
new
kata kunci. Anda tidak dapat memanggil konstruktor beberapa kali, karena konstruktor tidak dirancang untuk melakukannya.Tentang metode: Suatu metode dapat dipanggil sebanyak yang Anda inginkan (Bahkan tidak pernah) dan kompiler mengetahuinya.
skenario 1
foo
adalah variabel instan . Ketika kita membuatTest
objek kelas maka variabel instanfoo
, akan disalin di dalam objekTest
kelas. Jika kita menetapkanfoo
di dalam konstruktor, maka kompiler tahu bahwa konstruktor akan dipanggil hanya sekali, jadi tidak ada masalah menugaskannya di dalam konstruktor.Jika kita menetapkan
foo
di dalam suatu metode, kompiler tahu bahwa suatu metode dapat dipanggil beberapa kali, yang berarti nilainya harus diubah beberapa kali, yang tidak diperbolehkan untuk suatufinal
variabel. Jadi kompiler memutuskan konstruktor adalah pilihan yang bagus! Anda dapat menetapkan nilai ke variabel akhir hanya satu kali.Skenario 2
foo
sekarang menjadi variabel statis . Ketika kita membuat turunanTest
kelas,foo
tidak akan disalin ke objek karenafoo
statis. Sekarangfoo
bukan properti independen dari setiap objek. Ini adalah propertiTest
kelas. Tetapifoo
dapat dilihat oleh banyak objek dan jika setiap objek yang dibuat dengan menggunakannew
kata kunci yang pada akhirnya akan memanggilTest
konstruktor yang mengubah nilai pada saat beberapa objek dibuat (Ingatstatic foo
tidak disalin di setiap objek, tetapi dibagi antara beberapa objek .)Skenario 3
Di atas
Modification-2
adalah dari pertanyaan Anda. Dalam kasus di atas, Anda tidak mengubah objek referensi pertama, tetapi Anda menambahkan konten di dalamnyafoo
yang diizinkan. Compiler mengeluh jika Anda mencoba untuk menetapkannew ArrayList()
kefoo
variabel referensi.Aturan Jika Anda telah menginisialisasi
final
variabel, maka Anda tidak dapat mengubahnya untuk merujuk ke objek yang berbeda. (Dalam hal iniArrayList
)kelas akhir tidak dapat disubklasifikasikan metode
akhir tidak dapat diganti. (Metode ini dalam superclass) metode
terakhir dapat menimpa. (Baca ini dengan cara tata bahasa. Metode ini dalam subkelas)
sumber
foo
akan ditetapkan beberapa kali meskipun penunjukan akhir jikafoo
diatur dalam kelas Tes dan beberapa contoh Uji dibuat?foo
bisa jadi .. beberapa objek.) Apakah itu berarti, jika saya membuat beberapa objek sekaligus, maka objek mana yang menginisialisasi variabel akhir tergantung pada eksekusi?final
ke alamat memori yang dirujuk olehfoo
yang merupakan ArrayList. Anda tidak menetapkanfinal
alamat memori yang dirujuk oleh elemen pertamafoo
(atau elemen apa pun dalam hal ini). Karena itu Anda tidak bisa berubahfoo
tetapi Anda bisa berubahfoo[0]
.foo = new ArrayList();
-foo
merujuk ke variabel statis karena kita berada di dalam kelas yang sama.final
variabel sama seperticonst
kata kunci dalam C ++?Kata kunci terakhir memiliki banyak cara untuk digunakan:
Penggunaan lainnya:
Variabel kelas statis akan ada dari awal JVM, dan harus diinisialisasi di kelas. Pesan kesalahan tidak akan muncul jika Anda melakukan ini.
sumber
static
bidang (asalkan tidakfinal
) sebanyak yang Anda inginkan. Lihat wiki ini untuk perbedaan antara penugasan dan inisialisasi .Kata
final
kunci dapat diartikan dalam dua cara berbeda tergantung pada apa yang digunakannya:Jenis nilai: Untuk
int
s,double
s dll, itu akan memastikan bahwa nilai tidak dapat berubah,Jenis referensi: Untuk referensi ke objek,
final
pastikan bahwa referensi tidak akan pernah berubah, artinya akan selalu merujuk ke objek yang sama. Itu tidak membuat jaminan apa pun tentang nilai-nilai di dalam objek yang dirujuk tetap sama.Dengan demikian,
final List<Whatever> foo;
pastikan bahwafoo
selalu mengacu pada daftar yang sama , tetapi isi dari daftar tersebut dapat berubah seiring waktu.sumber
Jika Anda membuat
foo
statis, Anda harus menginisialisasi dalam konstruktor kelas (atau sebaris di mana Anda mendefinisikannya) seperti contoh berikut.Konstruktor kelas (bukan turunan):
Di barisan:
Masalahnya di sini bukanlah bagaimana
final
modifier bekerja, melainkan bagaimanastatic
modifier bekerja.The
final
pengubah memberlakukan inisialisasi referensi Anda pada saat panggilan untuk Rampungkan konstruktor Anda (yaitu Anda harus menginisialisasi dalam constructor).Ketika Anda menginisialisasi atribut in-line, itu akan diinisialisasi sebelum kode yang Anda tetapkan untuk konstruktor dijalankan, sehingga Anda mendapatkan hasil berikut:
foo
inistatic
,foo = new ArrayList()
akan dieksekusi sebelumstatic{}
konstruktor yang telah Anda tetapkan untuk kelas Anda dijalankanfoo
tidakstatic
,foo = new ArrayList()
akan dieksekusi sebelum konstruktor Anda dijalankanKetika Anda tidak
final
menginisialisasi atribut in-line, pengubah memberlakukan bahwa Anda menginisialisasi dan bahwa Anda harus melakukannya di konstruktor. Jika Anda juga memilikistatic
pengubah, konstruktor Anda harus menginisialisasi atribut adalah blok inisialisasi kelas ':static{}
.Kesalahan yang Anda dapatkan dalam kode Anda adalah dari fakta yang
static{}
dijalankan ketika kelas dimuat, sebelum saat Anda instantiate objek kelas itu. Dengan demikian, Anda belum menginisialisasifoo
ketika kelas dibuat.Pikirkan
static{}
blok sebagai konstruktor untuk objek bertipeClass
. Di sinilah Anda harus melakukan inisialisasistatic final
atribut kelas Anda (jika tidak dilakukan inline).Catatan:
The
final
menjamin pengubah const-ness hanya untuk tipe primitif dan referensi.Saat Anda mendeklarasikan
final
objek, yang Anda dapatkan adalahfinal
referensi ke objek itu, tetapi objek itu sendiri tidak konstan.Apa yang sebenarnya Anda capai ketika mendeklarasikan
final
atribut adalah bahwa, setelah Anda mendeklarasikan objek untuk tujuan spesifik Anda (sepertifinal List
yang telah Anda nyatakan), itu dan hanya objek itu yang akan digunakan untuk tujuan itu: Anda tidak akan dapat mengubahList foo
ke lainList
, tetapi Anda masih dapat mengubah AndaList
dengan menambahkan / menghapus item (yangList
Anda gunakan akan sama, hanya dengan isinya diubah).sumber
Ini pertanyaan wawancara yang sangat bagus. Kadang-kadang mereka bahkan mungkin bertanya kepada Anda apa perbedaan antara objek akhir dan objek abadi.
1) Ketika seseorang menyebutkan objek akhir, itu berarti bahwa referensi tidak dapat diubah, tetapi statusnya (variabel instan) dapat diubah.
2) Objek yang tidak berubah adalah objek yang kondisinya tidak dapat diubah, tetapi referensi dapat diubah. Ex:
variabel ref x dapat diubah untuk menunjukkan string yang berbeda, tetapi nilai "abc" tidak dapat diubah.
3) Variabel instance (bidang non statis) diinisialisasi ketika konstruktor dipanggil. Jadi, Anda dapat menginisialisasi nilai ke variabel di dalam konstruktor.
4) "Tetapi saya melihat bahwa Anda dapat mengubah nilai dalam konstruktor / metode kelas". - Anda tidak dapat mengubahnya di dalam suatu metode.
5) Variabel statis diinisialisasi selama pemuatan kelas. Jadi Anda tidak dapat menginisialisasi di dalam konstruktor, itu harus dilakukan bahkan sebelum itu. Jadi, Anda perlu menetapkan nilai ke variabel statis selama deklarasi itu sendiri.
sumber
Kata
final
kunci dalam java digunakan untuk membatasi pengguna. Katafinal
kunci java dapat digunakan dalam banyak konteks. Final dapat:Kata
final
kunci dapat diterapkan dengan variabel,final
variabel yang tidak memiliki nilai, disebutfinal
variabel kosong ataufinal
variabel tidak diinisialisasi . Ini dapat diinisialisasi dalam konstruktor saja.final
Variabel kosong dapatstatic
juga yang akan diinisialisasi distatic
blok saja.Variabel akhir Java:
Jika Anda membuat setiap variabel seperti
final
, Anda tidak dapat mengubah nilai darifinal
variabel (Ini akan konstan).Contoh
final
variabelAda speedlimit variabel akhir, kita akan mengubah nilai variabel ini, tetapi itu tidak dapat diubah karena variabel akhir setelah diberi nilai tidak pernah bisa diubah.
Kelas akhir Jawa:
Jika Anda menjadikan kelas apa pun sebagai
final
, Anda tidak dapat memperpanjangnya .Contoh kelas akhir
Metode final Java:
Jika Anda membuat metode apa pun sebagai final, Anda tidak dapat menimpanya .
Contoh
final
metode (lari () di Honda tidak bisa menimpa lari () di Sepeda)dibagikan dari: http://www.javatpoint.com/final-keyword
sumber
Layak untuk menyebutkan beberapa definisi langsung:
Kelas / Metode
Variabel
final
pada dasarnya hindari overwrite / superscribe oleh apa pun (subclass, variabel "tetapkan"), tergantung pada kasusnya.sumber
final
adalah kata kunci yang dilindungi undang-undang di Jawa untuk membatasi pengguna dan dapat diterapkan ke variabel anggota, metode, kelas, dan variabel lokal. Variabel akhir sering dideklarasikan denganstatic
kata kunci di Jawa dan diperlakukan sebagai konstanta. Sebagai contoh:Saat kami menggunakan
final
kata kunci dengan deklarasi variabel, nilai yang disimpan di dalam variabel itu tidak dapat diubah belakangan.Sebagai contoh:
Catatan : Kelas yang dinyatakan sebagai final tidak dapat diperpanjang atau diwariskan (yaitu, tidak ada subkelas dari kelas super). Juga baik untuk dicatat bahwa metode yang dinyatakan sebagai final tidak dapat ditimpa oleh subclass.
Manfaat menggunakan kata kunci terakhir dibahas di utas ini .
sumber
the value stored inside that variable cannot be changed latter
sebagian benar. Memang benar hanya untuk tipe data primitif. Dalam hal objek dibuatfinal
, seperti arraylist, nilainya dapat berubah tetapi bukan referensi. Terima kasih!Misalkan Anda memiliki dua kotak uang, merah dan putih. Anda menetapkan kotak uang ini hanya dua anak dan mereka tidak diizinkan menukar kotak mereka. Jadi Anda memiliki kotak uang merah atau putih (final) Anda tidak dapat memodifikasi kotak tetapi Anda dapat menaruh uang di kotak Anda. Tidak ada yang peduli (Modifikasi-2).
sumber
Baca semua jawabannya.
Ada kasus pengguna lain di mana
final
kata kunci dapat digunakan yaitu dalam argumen metode:Dapat digunakan untuk variabel yang tidak boleh diubah.
sumber
Ketika Anda membuatnya final statis, itu harus diinisialisasi dalam blok inisialisasi statis
sumber
Kata
final
kunci menunjukkan bahwa suatu variabel hanya dapat diinisialisasi satu kali. Dalam kode Anda, Anda hanya melakukan satu inisialisasi akhir sehingga persyaratan terpenuhi. Pernyataan ini melakukan inisialisasi tunggalfoo
. Perhatikan bahwafinal
! = Tidak berubah, itu hanya berarti bahwa referensi tidak dapat berubah.Ketika Anda mendeklarasikan
foo
sebagaistatic final
variabel harus diinisialisasi ketika kelas dimuat dan tidak dapat mengandalkan instantiasi (alias panggil konstruktor) untuk menginisialisasifoo
karena bidang statis harus tersedia tanpa turunan dari kelas. Tidak ada jaminan bahwa konstruktor akan dipanggil sebelum menggunakan bidang statis.Ketika Anda menjalankan metode Anda di bawah
static final
skenarioTest
kelas dimuat sebelum instantiatingt
saat ini tidak ada instantiasifoo
makna yang belum diinisialisasi sehinggafoo
disetel ke default untuk semua objek yang adanull
. Pada titik ini saya menganggap kode Anda melemparNullPointerException
ketika Anda mencoba untuk menambahkan item ke daftar.sumber
Pertama-tama, tempat dalam kode Anda di mana Anda menginisialisasi (mis. Menetapkan untuk pertama kalinya) foo ada di sini:
foo adalah objek (dengan tipe Daftar) sehingga merupakan tipe referensi , bukan tipe nilai (seperti int). Dengan demikian, ia menyimpan referensi ke lokasi memori (mis. 0xA7D2A834) tempat elemen Daftar Anda disimpan. Garis seperti ini
jangan ubah nilai foo (yang, sekali lagi, hanya referensi ke lokasi memori). Sebagai gantinya, mereka hanya menambahkan elemen ke lokasi memori yang dirujuk. Untuk melanggar kata kunci terakhir , Anda harus mencoba menetapkan ulang foo sebagai berikut lagi:
Itu akan memberi Anda kesalahan kompilasi.
Sekarang, dengan hal itu, pikirkan apa yang terjadi ketika Anda menambahkan kata kunci statis .
Ketika Anda TIDAK memiliki kata kunci statis, setiap objek yang instantiate kelas memiliki salinan foo sendiri. Oleh karena itu, konstruktor memberikan nilai pada salinan kosong dari variabel foo, yang benar-benar baik-baik saja.
Namun, ketika Anda DO memiliki kata kunci statis, hanya ada satu foo di memori yang terkait dengan kelas. Jika Anda membuat dua objek atau lebih, konstruktor akan berusaha untuk menetapkan ulang satu foo setiap kali, melanggar kata kunci terakhir .
sumber
final
hanya mengikat referensi ke objek tertentu. Anda bebas mengubah 'keadaan' objek itu, tetapi bukan objek itu sendiri.sumber
Berikut ini adalah konteks yang berbeda di mana final digunakan.
Variabel akhir Variabel akhir hanya dapat ditetapkan satu kali. Jika variabel adalah referensi, ini berarti bahwa variabel tidak dapat terikat kembali untuk referensi objek lain.
variabel akhir dapat diberi nilai nanti (tidak wajib untuk menetapkan nilai saat dideklarasikan), tetapi hanya sekali.
Kelas akhir Kelas akhir tidak dapat diperpanjang (diwariskan)
Metode akhir Metode akhir tidak dapat ditimpa oleh subclass.
sumber
Saya berpikir untuk menulis jawaban yang diperbarui dan mendalam di sini.
final
kata kunci dapat digunakan di beberapa tempat.A
final class
berarti tidak ada kelas lain yang bisa memperpanjang kelas akhir itu. Ketika Java Run Time ( JRE ) tahu referensi objek dalam tipe kelas akhir (katakanlah F), ia tahu bahwa nilai referensi itu hanya bisa dalam tipe F.Ex:
Jadi ketika mengeksekusi metode apa pun dari objek itu, metode itu tidak perlu diselesaikan pada saat run time menggunakan tabel virtual . yaitu polimorfisme run-time tidak dapat diterapkan. Jadi jangka waktu tidak peduli tentang itu. Yang berarti menghemat waktu pemrosesan, yang akan meningkatkan kinerja.
A
final method
dari sembarang kelas berarti bahwa setiap kelas anak yang memperluas kelas itu tidak dapat menggantikan metode akhir itu. Jadi perilaku run time dalam skenario ini juga sangat sama dengan perilaku sebelumnya yang saya sebutkan untuk kelas.Jika seseorang menentukan jenis apa pun di atas sebagai
final
, itu berarti bahwa nilainya telah selesai, sehingga nilainya tidak dapat diubah .Ex:
Untuk bidang, parameter lokal
Untuk parameter metode
Ini berarti bahwa nilai dari nilai
final
referensi tidak dapat diubah. yaitu hanya satu inisialisasi yang diizinkan. Dalam skenario ini, dalam jangka waktu, karena JRE tahu bahwa nilai tidak dapat diubah, ini memuat semua nilai akhir ini (dari referensi akhir) ke dalam cache L1 . Karena tidak perlu untuk memuat kembali lagi dan lagi dari memori utama . Kalau tidak dimuat ke L2 cache dan melakukan waktu ke waktu memuat dari memori utama. Jadi ini juga merupakan peningkatan kinerja.Jadi dalam semua 3 skenario di atas, ketika kami belum menentukan
final
kata kunci di tempat yang bisa kami gunakan, kami tidak perlu khawatir, optimisasi kompiler akan melakukannya untuk kami. Ada juga banyak hal lain yang dilakukan optimasi kompiler untuk kita. :)sumber
Di atas semuanya benar. Selanjutnya jika Anda tidak ingin orang lain membuat sub kelas dari kelas Anda, maka nyatakan kelas Anda sebagai final. Maka itu menjadi tingkat daun hierarki pohon kelas Anda yang tidak ada yang bisa memperpanjangnya. Ini adalah praktik yang baik untuk menghindari hierarki kelas yang besar.
sumber