java - Static 标识的字段或者是代码块,真的是在类加载的时候初始化的吗?
PHPz
PHPz 2017-04-18 10:52:20
0
8
652
class AAA {
    static {
        System.out.println("class AAA static block println"); // 并没有打印此句
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println("hello world!");
    }
}

一直以来都以为 static 标识的代码块或者是字段,都是在类加载的时候就被执行或者赋值了,但是这么一看....感觉自己的世界观都要被刷新了。

所以此处是类没有被加载吗?还是说我们一直以来认为的,静态代码块、字段都在类加载的时候被初始化的,这个观点是错误的?

在《深入理解Java虚拟机:JVM高级特性与最佳实践 第2版》中找到一些线索,如下图:

所以,照这么说,是在第一次主动访问该类的时候执行?小弟好生迷惑啊....大家快说说你们的观点

PHPz
PHPz

学习是最好的投资!

membalas semua(8)
左手右手慢动作

Pemulaan kelas dan pemulaan objek.

Blok kod dan pembolehubah yang terkandung dalam statik hanya dilaksanakan apabila kelas dimulakan, dan anda juga mengetahui lima syarat untuk permulaan.

Sila terangkan dengan jelas.
Pertama sekali, walaupun anda meletakkannya dalam fail .java yang sama, selepas penyusunan, ia masih dua fail kelas yang berbeza Jika anda tidak percaya saya, lihat fail .class yang dijana di bawah yang sepadan bungkusan tong sampah.
Kedua, apabila kelas dimulakan, pembolehubah statik kelas akan dimulakan dan blok kod statik akan dijalankan. Oleh itu, mesin maya menetapkan lima syarat permulaan, seperti penggunaan arahan baru, getstatic, putstatic, kelas di mana fungsi utama terletak, refleksi, kelas induk, dll. Walau bagaimanapun, kecuali untuk lima situasi ini, permulaan kelas tidak boleh dicetuskan. Seperti yang ditunjukkan dalam kod anda, dalam Main.class, tiada panggilan atau hubungan ibu bapa-anak atau refleksi tentang AAA.class. Oleh itu, AAA.class secara semula jadi tidak akan dimulakan.

Anda boleh membaca blog lain tentang proses pemuatan kelas java

Faham?

阿神

-XX:+TraceClassLoading
Tambah ini dan anda akan mendapati AAA tidak dimuatkan

洪涛

Terdapat dua konsep yang perlu disentuh di sini:

  1. Mekanisme pemuatan kelas

  2. Java, pengkompil, bytecode, spesifikasi dan pelaksanaan JVM.

Pemuatan kelas diselesaikan melalui pemuat kelas (Pemuat Kelas) Strategi pemuatan khusus bergantung pada pelaksanaan khusus JVM Secara umumnya, ia boleh dibahagikan kepada dua jenis:

  1. Lapar memuatkan, memuatkan asalkan ia dirujuk oleh kelas lain.

  2. Malas memuatkan, memuatkan kelas hanya apabila ia diakses.

Java, pengkompil, bytecode dan JVM mempunyai spesifikasi mereka sendiri dan berfungsi bersama melalui spesifikasi:

Butang kompil menyusun kod Java ke dalam fail kod bait piawai Setiap kelas (kelas luaran, kelas dalaman, kelas tanpa nama) akan disusun ke dalam fail kod bait berasingan (fail kelas), dan JVM memuatkan kelas Pada masa ini. , ia dimuatkan satu demi satu daripada fail kelas ini.

Sekarang kembali kepada kod anda:

Dalam lapisan Java, anda meletakkan dua kelas AAA dan Utama dalam satu fail Selepas penyusunan, pengkompil menjana dua fail kelas: AAA.class dan Main.class.
Kedua-dua kelas adalah bersama dari segi organisasi kod, tetapi mereka bebas selepas penyusunan, dan Utama tidak merujuk AAA, jadi tidak kira kaedah pemuatan kelas mana yang digunakan, ia tidak akan mencetuskan pemuatan kelas AAA, iaitu Blok kod statik dalam AAA tidak akan dilaksanakan.

左手右手慢动作

Saya sangat berterima kasih kepada netizen yang bersemangat di atas atas jawapan mereka!

Pengesahan

Kelas AAA memang tidak dimuatkan, hanya kelas Utama dimuatkan (tangkapan skrin soalan: keadaan permulaan keempat, kelas utama dimuatkan secara automatik oleh jvm)

java -XX:+TraceClassLoading Main

Kesimpulan

medan statik|blok kod dalam kelas benar-benar dimulakan atau dilaksanakan apabila kelas dimuatkan!

Sambungan

Bagaimana untuk mengetahui sama ada kelas telah dimuatkan oleh jvm?

Ini juga merupakan masalah yang saya hadapi Pada mulanya, saya fikir selagi perintah javac dilaksanakan, kelas akan dimuatkan oleh jvm arahan hanya menukar fail .java menjadi .class yang boleh difahami oleh jvm.

Jadi bagaimana anda tahu sama ada kelas telah dimuatkan oleh jvm?
Menurut "Pemahaman Mendalam tentang Mesin Maya Java: Ciri Lanjutan JVM dan Amalan Terbaik Edisi Ke-2" dan jawapan bersemangat daripada netizen, tiada masa yang jelas menetapkan bila ia akan dimuatkan!

Tetapi! jvm dengan jelas menetapkan masa apabila kelas dimulakan - ini ialah empat jenis dalam tangkapan skrin di atas! Pemuatan kelas diutamakan daripada pemulaan kelas, jadi di sini, kita boleh berfikir sementara bahawa situasi ini ialah keadaan yang mencetuskan pemuatan kelas.

Abang saya jahil dan merumuskan sesuatu yang salah, tolong betulkan saya! Terima kasih

PHPzhong

Letakkan Main.java dan AAA.java anda dalam folder yang sama,

Tulis

dalam fungsi utama
Class.forName("AAA");

Laksanakan

大家讲道理

Apabila kaedah utama dilaksanakan, hanya kelas Utama akan dimuatkan Kelas AAA tidak digunakan dalam kelas Utama, dan kelas AAA tidak akan dimuatkan. Ini tidak bermakna menulis kelas AAA dan Utama fail yang sama akan menyebabkan mereka dimuatkan secara serentak

大家讲道理

Kelas AAA bukan baharu di tempat lain, ia juga tidak mendapat atau menetapkan medan statik secara sepadan, dan juga tidak menggunakan kaedah statik.
Jadi ia tidak akan dimulakan secara automatik.

迷茫

diletakkan dalam dua kelas Kelas utama yang diisytiharkan sebagai awam mula melaksanakan kelas itu tidak digunakan dan tidak akan dimuatkan apatah lagi dimulakan

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!