Sejauh yang saya mengerti "blok inisialisasi statis" digunakan untuk mengatur nilai-nilai bidang statis jika tidak dapat dilakukan dalam satu baris.
Tapi saya tidak mengerti mengapa kita perlu blok khusus untuk itu. Sebagai contoh, kami menyatakan bidang sebagai statis (tanpa penugasan nilai). Dan kemudian menulis beberapa baris kode yang menghasilkan dan menetapkan nilai ke bidang statis yang dinyatakan di atas.
Mengapa kita perlu garis ini di blok khusus seperti: static {...}
?
{...}
vsstatic {...}
. (dalam hal ini Jon Skeet pasti menjawab pertanyaan Anda dengan lebih baik)Jawaban:
The blok non-statis:
Mendapat panggilan setiap kali instance kelas dibangun. The blok statis hanya dipanggil sekali , ketika kelas itu sendiri diinisialisasi, tidak peduli berapa banyak objek dari jenis yang Anda buat.
Contoh:
Ini mencetak:
sumber
Jika mereka tidak berada di blok inisialisasi statis, di manakah mereka? Bagaimana Anda mendeklarasikan variabel yang hanya dimaksudkan lokal untuk keperluan inisialisasi, dan membedakannya dari bidang? Misalnya, bagaimana Anda ingin menulis:
Jika
first
dansecond
tidak di blok, mereka akan terlihat seperti bidang. Jika mereka berada di blok tanpastatic
di depannya, itu akan dihitung sebagai contoh inisialisasi blok bukan blok inisialisasi statis, sehingga akan dieksekusi sekali per instance yang dibangun daripada total sekali.Sekarang dalam kasus khusus ini, Anda bisa menggunakan metode statis sebagai gantinya:
... tetapi itu tidak berfungsi ketika ada beberapa variabel yang ingin Anda tetapkan dalam blok yang sama, atau tidak ada (misalnya jika Anda hanya ingin mencatat sesuatu - atau mungkin menginisialisasi perpustakaan asli).
sumber
private static int widgets = 0; static{widgets = 2;}
private static int widgets = 0; static{widgets = 2;}
Mengetahui bahwa penugasan '=' terjadi secara berurutan, yang berarti penandaan '=' akan ditetapkan terlebih dahulu. Contoh di atas akan memberikan 'widget' nilai 2. (PS tidak tahu bahwa komentar hanya dapat diedit dalam 5 menit ...)Ini sebuah contoh:
Kode di bagian "statis" akan dieksekusi pada waktu pemuatan kelas, sebelum instance kelas dibuat (dan sebelum metode statis apa pun dipanggil dari tempat lain). Dengan begitu Anda dapat memastikan bahwa semua sumber daya kelas siap digunakan.
Juga dimungkinkan untuk memiliki blok penginisialisasi non-statis. Mereka bertindak seperti ekstensi ke set metode konstruktor yang ditentukan untuk kelas. Mereka terlihat seperti blok penginisialisasi statis, kecuali kata kunci "statis" tidak aktif.
sumber
Ini juga berguna ketika Anda sebenarnya tidak ingin memberikan nilai pada apa pun, seperti memuat beberapa kelas hanya sekali selama runtime.
Misalnya
Hei, ada manfaat lain, Anda bisa menggunakannya untuk menangani pengecualian. Bayangkan di
getStuff()
sini melemparException
yang benar-benar termasuk dalam blok penangkap:maka
static
inisialisasi berguna di sini. Anda dapat menangani pengecualian di sana.Contoh lain adalah melakukan hal-hal setelah itu yang tidak dapat dilakukan selama menugaskan:
Untuk kembali ke contoh driver JDBC, setiap driver JDBC yang layak itu sendiri juga menggunakan
static
penginisialisasi untuk mendaftarkan dirinya diDriverManager
. Juga lihat ini dan ini jawabannya.sumber
Saya akan mengatakan
static block
ini hanya gula sintaksis. Tidak ada yang bisa Anda lakukan denganstatic
blok dan tidak dengan apa pun.Untuk menggunakan kembali beberapa contoh yang diposting di sini.
Potongan kode ini dapat ditulis ulang tanpa menggunakan
static
penginisialisasi.Metode # 1: Dengan
static
Metode # 2: Tanpa
static
sumber
Ada beberapa alasan aktual mengapa diperlukan:
static final
anggota yang inisialisasi mungkin melemparkan pengecualianstatic final
anggota dengan nilai yang dihitungOrang-orang cenderung menggunakan
static {}
blok sebagai cara yang nyaman untuk menginisialisasi hal-hal yang bergantung pada kelas dalam runtime juga - seperti memastikan bahwa kelas tertentu dimuat (misalnya, driver JDBC). Itu bisa dilakukan dengan cara lain; Namun, dua hal yang saya sebutkan di atas hanya dapat dilakukan dengan konstruksi sepertistatic {}
blok.sumber
Anda bisa mengeksekusi bit kode sekali untuk kelas sebelum objek dibangun di blok statis.
Misalnya
sumber
Adalah kesalahpahaman umum untuk berpikir bahwa blok statis hanya memiliki akses ke bidang statis. Untuk ini saya ingin menunjukkan potongan kode di bawah ini yang sering saya gunakan dalam proyek kehidupan nyata (disalin sebagian dari jawaban lain dalam konteks yang sedikit berbeda):
Di sini penginisialisasi digunakan untuk mempertahankan indeks (
ALIAS_MAP
), untuk memetakan set alias kembali ke tipe enum asli. Ini dimaksudkan sebagai perluasan ke metode valueOf bawaan yang disediakan olehEnum
dirinya sendiri.Seperti yang Anda lihat, penginisialisasi statis mengakses bahkan
private
bidangaliases
. Penting untuk memahami bahwastatic
blok sudah memiliki akses keEnum
instance nilai (misalnyaENGLISH
). Ini karena urutan inisialisasi dan eksekusi dalam kasusEnum
tipe , seperti jikastatic private
bidang telah diinisialisasi dengan instance sebelumstatic
blok dipanggil:Enum
konstanta yang bidang statis implisit. Ini memerlukan konstruktor Enum dan blok instance, dan inisialisasi instance juga terjadi terlebih dahulu.static
blok dan inisialisasi bidang statis dalam urutan kejadian.Inisialisasi rusak ini (konstruktor sebelum
static
blok) penting untuk dicatat. Ini juga terjadi ketika kita menginisialisasi bidang statis dengan instance yang mirip dengan Singleton (penyederhanaan dibuat):Apa yang kita lihat adalah output berikut:
Yang jelas adalah bahwa inisialisasi statis sebenarnya dapat terjadi sebelum konstruktor, dan bahkan setelah:
Cukup mengakses Foo dalam metode utama, menyebabkan kelas dimuat dan inisialisasi statis dimulai. Tetapi sebagai bagian dari inisialisasi Statis kita kembali memanggil konstruktor untuk bidang statis, setelah itu melanjutkan inisialisasi statis, dan melengkapi konstruktor yang dipanggil dari dalam metode utama. Situasi yang agak rumit yang saya harap dalam coding normal kita tidak harus berurusan dengan.
Untuk info lebih lanjut tentang ini, lihat buku " Java Efektif ".
sumber
aliases
bukan berarti blok statis dapat mengakses anggota yang tidak statis.aliases
diakses melaluiLanguage
nilai yang dikembalikan oleh metode / static /values()
. Seperti yang Anda sebutkan, fakta bahwa variabel enum sudah tersedia pada saat itu adalah bit yang tidak biasa - anggota non-statis dari kelas reguler tidak akan dapat diakses dalam situasi ini.class Foo { static final Foo Inst1; static final Foo Inst2; static{ Inst1 = new Foo("Inst1"); Inst2 = new Foo("Inst2"); } static { System.out.println("Inst1: " + Inst1.member); System.out.println("Inst2: " + Inst2.member); } private final String member; private Foo(String member){ this.member = member; } }
Kode di atas tidak berbeda dari contoh enum dan masih memungkinkan akses variabel instan di dalam blok statisEnum
. Ini adalah cara terbaik untuk menjamin bahwa kami menunjuk ke instance tunggal - lihat di sini . Dan untuk poin Anda, saya telah membuat beberapa pembaruan.Jika variabel statis Anda perlu diset pada saat runtime maka sebuah
static {...}
blok sangat membantu.Misalnya, jika Anda perlu mengatur anggota statis ke nilai yang disimpan dalam file konfigurasi atau database.
Juga berguna ketika Anda ingin menambahkan nilai ke anggota statis
Map
karena Anda tidak dapat menambahkan nilai-nilai ini dalam pernyataan anggota awal.sumber
Jadi Anda memiliki bidang statis (ini juga disebut "variabel kelas" karena itu milik kelas dan bukan turunan dari kelas; dengan kata lain itu terkait dengan kelas daripada dengan objek apa pun) dan Anda ingin menginisialisasi itu. Jadi jika Anda TIDAK ingin membuat turunan dari kelas ini dan Anda ingin memanipulasi bidang statis ini, Anda bisa melakukannya dengan tiga cara:
1- Cukup inisialisasi ketika Anda mendeklarasikan variabel:
2- Memiliki blok inisialisasi statis:
3 - Memiliki metode kelas (metode statis) yang mengakses variabel kelas dan menginisialisasi itu: ini adalah alternatif untuk blok statis di atas; Anda dapat menulis metode statis pribadi:
Sekarang mengapa Anda menggunakan blok inisialisasi statis daripada metode statis?
Terserah apa yang Anda butuhkan dalam program Anda. Tetapi Anda harus tahu bahwa blok inisialisasi statis dipanggil sekali dan satu-satunya keuntungan dari metode kelas adalah bahwa mereka dapat digunakan kembali nanti jika Anda perlu menginisialisasi ulang variabel kelas.
katakanlah Anda memiliki array yang kompleks dalam program Anda. Anda menginisialisasi (menggunakan untuk loop misalnya) dan kemudian nilai-nilai dalam array ini akan berubah sepanjang program tetapi kemudian pada beberapa titik Anda ingin menginisialisasi ulang itu (kembali ke nilai awal). Dalam hal ini Anda dapat memanggil metode statis pribadi. Jika Anda tidak perlu dalam program Anda untuk menginisialisasi ulang nilai-nilai, Anda bisa menggunakan blok statis dan tidak perlu untuk metode statis karena Anda tidak akan menggunakannya nanti dalam program.
Catatan: blok statis dipanggil dalam urutan yang muncul dalam kode.
Contoh 1:
Contoh 2:
sumber
Sebagai pelengkap, seperti kata @Pointy
Seharusnya menambahkan
System.loadLibrary("I_am_native_library")
ke blok statis.Ini akan menjamin tidak ada metode asli dipanggil sebelum perpustakaan terkait dimuat ke dalam memori.
Menurut loadLibrary dari oracle :
Jadi cukup tidak terduga, menempatkan System.loadLibrary tidak digunakan untuk menghindari perpustakaan dimuat berkali-kali.
sumber
Pertama-tama Anda perlu memahami bahwa kelas aplikasi Anda sendiri dipakai untuk
java.class.Class
objek selama runtime. Ini adalah ketika blok statis Anda dijalankan. Jadi Anda benar-benar dapat melakukan ini:dan itu akan mencetak "myInt is 1" ke konsol. Perhatikan bahwa saya belum membuat instance kelas apa pun.
sumber
sumber
blok statis digunakan untuk teknologi apa pun untuk menginisialisasi anggota data statis dengan cara yang dinamis, atau kita dapat mengatakan untuk inisialisasi dinamis dari anggota data statis blok statis sedang digunakan .. Karena untuk inisialisasi anggota data non statis kita memiliki konstruktor tetapi kita tidak memiliki tempat di mana kita dapat secara dinamis menginisialisasi anggota data statis
Sekarang int x statis saya akan menginisialisasi secara dinamis .. BCOZ ketika kompiler akan pergi ke Solution.x itu akan memuat Kelas Solusi dan beban blok statis pada waktu pemuatan kelas .. Jadi kita dapat secara dinamis menginisialisasi anggota data statis itu ..
}
sumber