Rumah >Java >javaTutorial >Membolehkan anda memahami kata kunci statik dalam Java sekaligus

Membolehkan anda memahami kata kunci statik dalam Java sekaligus

醉折花枝作酒筹
醉折花枝作酒筹ke hadapan
2021-08-04 17:49:462180semak imbas

Saya percaya bahawa ramai pelajar telah menemui soalan seperti ini. Mereka mungkin telah mencari maklumat itu dan kemudian terlupa jika mereka menemuinya lagi, mereka masih tidak dapat menjawabnya dengan betul. Seterusnya, melalui 4 langkah, saya akan membawa anda untuk membuka urutan pelaksanaan kod ini dan meringkaskan peraturan.

Soalan pembukaan untuk mengkaji susunan pelaksanaan kod:

public class Parent {
    static {
        System.out.println("Parent static initial block");
    }

    {
        System.out.println("Parent initial block");
    }

    public Parent() {
        System.out.println("Parent constructor block");

    }
}

public class Child extends Parent {
    static {
        System.out.println("Child static initial block");
    }

    {
        System.out.println("Child initial block");
    }
    
    private Hobby hobby = new Hobby();

    public Child() {
        System.out.println("Child constructor block");
    }
}

public class Hobby {
    static{
        System.out.println("Hobby static initial block");
    }

    public Hobby() {
        System.out.println("hobby constructor block");
    }
}

Apabila Child() baharu dilaksanakan, apakah yang dikeluarkan oleh kod di atas?

Saya percaya ramai pelajar yang menghadapi masalah sebegini mungkin telah menyemak maklumat tersebut dan kemudiannya terlupa jika terjumpa lagi, mereka masih tidak dapat menjawabnya dengan betul. Seterusnya, wakil kelas akan membawa anda melalui 4 langkah untuk merungkai urutan pelaksanaan kod ini dan meringkaskan peraturan.

1. Apakah yang dioptimumkan oleh pengkompil?

Dua keping kod berikut membandingkan perubahan sebelum dan selepas penyusunan:

Child.java sebelum penyusunan

public class Child extends Parent {
    static {
        System.out.println("Child static initial block");
    }
    {
        System.out.println("Child initial block");
    }
    
    private Hobby hobby = new Hobby();
    
    public Child() {
        System.out.println("Child constructor block");
    }
}

Child.class selepas kompilasi

public class Child extends Parent {
    private Hobby hobby;

    public Child() {
        System.out.println("Child initial block");
        this.hobby = new Hobby();
        System.out.println("Child constructor block");
    }

    static {
        System.out.println("Child static initial block");
    }
}

Ia boleh dilihat daripada perbandingan bahawa pengkompil mengalihkan blok permulaan dan operasi penetapan medan contoh sebelum kod pembina, dan mengekalkan susunan kod yang berkaitan. Malah, jika terdapat berbilang pembina, kod permulaan akan disalin dan dipindahkan.

Berdasarkan ini, susunan keutamaan pertama boleh diperolehi:

  • Kod permulaan >
Proses pemuatan kelas boleh dibahagikan secara kasar kepada tiga peringkat: Pemuatan-> Pautan-> jenis pencetus permulaan kelas Kes ") pencetus:

Apabila membuat instantiat objek menggunakan kata kunci baharu

  • Baca atau tetapkan medan statik a taip (malar" )

  • Memanggil kaedah statik jenis

  • Apabila menggunakan refleksi untuk memanggil kelas

  • Apabila memulakan kelas, jika didapati bahawa kelas induk belum dimulakan, permulaan kelas induk akan dicetuskan dahulu

  • Apabila mesin maya dimulakan, kaedah kelas utama (termasuk main() akan dimulakan dahulu )

  • Apabila contoh MethodHandle pertama kali dipanggil, mulakan kelas di mana kaedah yang ditunjuk oleh MethodHandle berada

  • Jika dalam antara muka Kaedah lalai (kaedah antara muka diubah suai lalai) ditakrifkan dan kelas pelaksanaan antara muka dimulakan, maka antara muka mesti dimulakan sebelum

  • antara entri 2 dan 3 ialah

    Malah, fasa permulaan ialah proses melaksanakan kaedah pembina kelas583d030be372af71281df966e84181a5 tindakan dan pembolehubah statik semua pembolehubah kelas diubah suai statik (blok{} statik), dan mengekalkan susunan kod ini muncul
Menurut item 5, JVM akan memastikan bahawa kelas induk. 583d030be372af71281df966e84181a5 Kaedah telah dilaksanakan

Untuk meringkaskan: mengakses pembolehubah kelas atau kaedah statik akan mencetuskan permulaan kelas, dan permulaan kelas adalah untuk melaksanakan 583d030be372af71281df966e84181a5, iaitu. , untuk melaksanakan tindakan pengubahsuaian statik dan blok statik{}, dan JVM memastikan bahawa pemulaan kelas induk dilakukan terlebih dahulu, dan kemudian pemulaan subkelas dilakukan Ini membawa kepada susunan keutamaan kedua:

Kod statik kelas induk> Kod statik subkelas

3 Kod statik hanya dilaksanakan sekali

Kita semua tahu bahawa kod statik (kecuali kaedah statik) hanya dilaksanakan sekali.
  • Anda tidak pernah terfikir tentang bagaimana mekanisme ini dijamin?
Pemuatan kelas aplikasi → Pemuat Kelas Sambungan → Pemuat Kelas Mula

Kelas yang ditulis dalam pembangunan harian dimuatkan oleh pemuat kelas aplikasi secara lalai, dan ia akan diwakilkan kepada kelas induknya: pemuat kelas sambungan. Pemuat kelas sambungan seterusnya mewakilkan kepada kelas induknya: pemuat kelas permulaan. Hanya apabila pemuat kelas induk melaporkan bahawa ia tidak dapat menyelesaikan permintaan pemuatan, pemuat anak akan cuba menyelesaikan pemuatan dengan sendirinya Proses ini adalah perwakilan induk. Hubungan ibu bapa-anak antara ketiga-tiga tidak dicapai melalui pewarisan, tetapi melalui mod gabungan.

Pelaksanaan proses ini juga sangat mudah Kod pelaksanaan utama ditunjukkan di bawah:

Dengan ulasan, saya percaya ia mudah difahami oleh semua orang.

Ia boleh dilihat daripada kod yang diwakilkan oleh ibu bapa bahawa di bawah pemuat kelas yang sama, kelas hanya boleh dimuatkan sekali, yang mengehadkannya kepada hanya dimulakan sekali. Oleh itu, kod statik dalam kelas (kecuali kaedah statik) hanya dilaksanakan sekali apabila kelas dimulakan

4 7e51f00a783d7eb8f68358439dee7daf

Kod yang dijana secara automatik oleh pengkompil telah diperkenalkan sebelum Pembina Kelas: kaedah 583d030be372af71281df966e84181a5 ia akan mengumpulkan tindakan tugasan dan blok pernyataan statik (blok{} statik) semua pembolehubah kelas yang diubah suai statik dan mengekalkan susunan penampilan kod itu dilaksanakan apabila kelas dimulakan

Sehubungan itu, pengkompil juga akan menjana kaedah 7e51f00a783d7eb8f68358439dee7daf yang akan mengumpul tindakan tugasan medan contoh, kod dalam blok pernyataan permulaan ({}) dan pembina (Pembina), dan mengekalkan susunan kemunculan kod , ia akan melaksanakan

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{
    // 首先检查该类是否被加载过
    // 如果加载过,直接返回该类
    Class<?> c = findLoadedClass(name);
    if (c == null) {
        try {
            if (parent != null) {
                c = parent.loadClass(name, false);
            } else {
                c = findBootstrapClassOrNull(name);
            }
        } catch (ClassNotFoundException e) {
            // 如果父类抛出ClassNotFoundException
            // 说明父类无法完成加载请求
        }

        if (c == null) {
            // 如果父类无法加载,转由子类加载
            c = findClass(name);
        }
    }
    if (resolve) {
        resolveClass(c);
    }
    return c;
}
selepas arahan baharu, apabila kita baharu kelas, jika JVM belum memuatkan kelas itu akan dimulakan dahulu dan kemudian dimulakan.

Pada ketika ini, peraturan keutamaan ketiga sedia untuk keluar:

  • Kod statik (blok{} statik, pernyataan tugasan medan statik) > Kod permulaan ({} blok, pernyataan tugasan medan contoh)

5 🎜> Gabungkan tiga peraturan sebelumnya dan ringkaskan dua berikut:

1 Kod statik (blok{} statik, pernyataan tugasan medan statik) > Kod pembina

2. Kod statik kelas induk > Kod statik subkelas

Menurut ringkasan sebelumnya, kod permulaan dan kod pembina dikumpul oleh pengkompil 7e51f00a783d7eb8f68358439dee7daf kod statik dikumpulkan ke dalam 583d030be372af71281df966e84181a5, jadi peraturan di atas digabungkan semula:

Kelas induk

> Kelas induk

> 🎜>583d030be372af71281df966e84181a5Sesuai dengan soalan pada mulanya, mari kita praktikkannya: 583d030be372af71281df966e84181a57e51f00a783d7eb8f68358439dee7dafApabila melaksanakan Child() baharu, kata kunci baharu mencetuskan permulaan kelas Child dan JVM mendapati ia mempunyai induk kelas , kemudian mulakan kelas Induk dahulu, mula melaksanakan kaedah 583d030be372af71281df966e84181a5 kelas Induk, dan kemudian laksanakan kaedah 583d030be372af71281df966e84181a5 kelas Anak (ingat apa yang dikumpul dalam 583d030be372af71281df966e84181a5?). 7e51f00a783d7eb8f68358439dee7daf

Kemudian mula membuat instantiation objek kelas Anak Pada masa ini, kami bersedia untuk melaksanakan kaedah 7e51f00a783d7eb8f68358439dee7daf Kami mendapati bahawa ia mempunyai kelas induk ; kaedah dahulu, dan kemudian laksanakan kelas anak 7e51f00a783d7eb8f68358439dee7daf (ingat apa yang dikumpul dalam 7e51f00a783d7eb8f68358439dee7daf?).

Saya percaya bahawa selepas membaca ini, anda sudah mempunyai jawapan kepada soalan pembukaan, anda juga boleh menulis urutan output terlebih dahulu, dan kemudian menulis kod untuk mengesahkannya sendiri.

Kesimpulan

Static sering digunakan dalam perkembangan harian Setiap kali saya menulis, selalu ada dua persoalan dalam fikiran saya Mengapa saya perlu menggunakan statik?

Seperti yang dapat dilihat daripada artikel ini, aplikasi statik melangkaui pembolehubah kelas dan semudah kaedah statik. Dalam corak singleton klasik, anda akan melihat pelbagai kegunaan statik Artikel seterusnya akan menulis tentang cara menulis corak singleton dengan cara yang mewah.

Atas ialah kandungan terperinci Membolehkan anda memahami kata kunci statik dalam Java sekaligus. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:segmentfault.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam