Kapan inisialisasi kelas statis terjadi?

110

Kapan bidang statis diinisialisasi? Jika saya tidak pernah membuat instance kelas, tetapi saya mengakses bidang statis, apakah SEMUA blok statis dan metode statis pribadi yang digunakan untuk membuat instance bidang statis pribadi dipanggil (dalam urutan) pada saat itu juga?

Bagaimana jika saya memanggil metode statis? Apakah itu juga menjalankan semua blok statis? Sebelum metode?

Tony R
sumber
Mirip untuk blok penginisialisasi statis: stackoverflow.com/questions/2007666/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Jawaban:

156

Inisialisasi statis kelas biasanya terjadi segera sebelum pertama kali salah satu peristiwa berikut terjadi:

  • sebuah instance dari kelas dibuat,
  • metode statis kelas dipanggil,
  • bidang statis kelas ditetapkan,
  • bidang statis non-konstan digunakan, atau
  • untuk kelas tingkat atas, pernyataan assert yang secara leksikal bertumpuk di dalam kelas dijalankan 1 .

Lihat JLS 12.4.1 .

Dimungkinkan juga untuk memaksa kelas untuk menginisialisasi (jika belum diinisialisasi) dengan menggunakan Class.forName(fqn, true, classLoader)atau bentuk singkatClass.forName(fqn)


1 - Poin terakhir ada di JLS untuk Java 6 hingga Java 8, tetapi tampaknya ada kesalahan dalam spesifikasi. Itu akhirnya diperbaiki di Java 9 JLS: lihat sumber .

Stephen C
sumber
9
Namun, ada kesalahan umum. Primitif dan Strings diganti dan tidak direferensikan. Jika Anda mereferensikan a class Other { public static final int VAL = 10; }dari beberapa kelas MyClass { private int = Other.VAL; }, kelas Othertersebut tidak akan dimuat. Sebaliknya, kompilator hanya akan mengganti bidang terakhir pada waktu kompilasi.
Rafael Winterhalter
6
@RafaelWinterhalter - ya ... itu adalah kasus bidang statis konstan .
Stephen C
2
@RafaelWinterhalter, ini tidak benar untuk semua primitif atau Stringvariabel 'final statis' , hanya variabel yang diinisialisasi oleh ekspresi konstan.
Lew Bloch
1
Ya, dan lapangan bahkan tidak perlu staticsementara ini kasus umum.
Rafael Winterhalter
1
Itu adalah bahasa pemrograman yang sama. Iya.
Stephen C
14

Bidang statis diinisialisasi selama "fase" inisialisasi pemuatan kelas (pemuatan, penautan, dan inisialisasi) yang mencakup inisialisasi statis dan inisialisasi bidang statisnya. Penginisialisasi statis dijalankan dalam urutan tekstual seperti yang ditentukan di kelas.

Perhatikan contohnya:

public class Test {

   static String sayHello()  {
      return a;
   }

   static String b = sayHello(); // a static method is called to assign value to b.
                                 // but its a has not been initialized yet.

   static String a = "hello";

   static String c = sayHello(); // assignes "hello" to variable c

    public static void main(String[] arg) throws Throwable {
         System.out.println(Test.b); // prints null
         System.out.println(Test.sayHello()); // prints "hello"
    }
}

Test.b mencetak nullkarena ketika sayHellodipanggil dalam lingkup statis, variabel statis atidak diinisialisasi.

naikus
sumber
6
Sebenarnya, inisialisasi bukanlah "fase" pemuatan kelas. Memang, beberapa kelas dapat dimuat tetapi tidak pernah diinisialisasi jika aplikasi tidak benar-benar menggunakannya.
Stephen C
@ Stephen C Anda benar, saya menggunakannya karena kurangnya istilah yang lebih baik, mungkin saya akan mengutipnya.
naikus
@ StephenC apakah itu berarti saat pemuatan Kelas berlangsung, ia menetapkan memori ke variabel statis (& metode) tetapi variabel statis tersebut tidak diinisialisasi dengan nilai yang diberikan dalam kode? karena di sini terlihat ketika b-> sayHello () -> a, 'a' ada di memori tetapi nilainya belum ditetapkan.
Shabbir Essaji
Pada dasarnya, ya.
Stephen C
1

Ya, semua penginisialisasi statis dijalankan sebelum Anda mengakses kelas untuk pertama kalinya. Jika ada cara lain, saya akan menyebutnya bug.

Nikita Rybak
sumber
Ada cara untuk merujuk ke kelas tanpa memulainya.
Lew Bloch