Pertanyaan Apa itu blok inisialisasi?


Kita dapat menempatkan kode dalam konstruktor atau metode atau blok inisialisasi. Apa gunanya blok inisialisasi? Apakah perlu bahwa setiap program java harus memilikinya?


75
2017-10-21 12:28


asal


Jawaban:


Pertama-tama, ada dua jenis blok inisialisasi:

  • blok inisialisasi instance, dan
  • blok inisialisasi statis.

Kode ini harus menggambarkan penggunaannya dan di mana urutannya dieksekusi:

public class Test {

    static int staticVariable;
    int nonStaticVariable;        

    // Static initialization block:
    // Runs once (when the class is initialized)
    static {
        System.out.println("Static initalization.");
        staticVariable = 5;
    }

    // Instance initialization block:
    // Runs each time you instantiate an object
    {
        System.out.println("Instance initialization.");
        nonStaticVariable = 7;
    }

    public Test() {
        System.out.println("Constructor.");
    }

    public static void main(String[] args) {
        new Test();
        new Test();
    }
}

Cetakan:

Static initalization.
Instance initialization.
Constructor.
Instance initialization.
Constructor.

Pencirian blok itialisasi berguna jika Anda ingin menjalankan beberapa kode terlepas dari konstruktor mana yang digunakan atau jika Anda ingin melakukan inisialisasi instance untuk kelas anonim.


143
2017-10-21 12:46



ingin menambahkan jawaban @ aioobe

Urutan eksekusi:

  1. blok inisialisasi statis kelas super

  2. blok inisialisasi statis kelas

  3. blok inisialisasi instance dari kelas super

  4. konstruktor kelas super

  5. blok inisialisasi instance kelas

  6. konstruktor kelas.

Beberapa poin tambahan yang perlu diingat (poin 1 adalah pengulangan jawaban @ aioobe):

  1. Kode dalam blok inisialisasi statis akan dieksekusi pada waktu muat kelas (dan ya, itu berarti hanya sekali per beban kelas), sebelum setiap contoh kelas dibangun dan sebelum metode statis apa pun dipanggil.

  2. Blok inisialisasi instance sebenarnya disalin oleh compiler Java ke dalam setiap konstruktor yang dimiliki kelas. Jadi setiap kali kode di blok inisialisasi instance dijalankan persis sebelum kode di konstruktor.


79
2018-03-14 15:36



jawaban yang bagus oleh aioobe menambahkan beberapa poin lagi

public class StaticTest extends parent {
    static {
        System.out.println("inside satic block");
    }

    StaticTest() {
        System.out.println("inside constructor of child");
    }

    {
        System.out.println("inside initialization block");
    }

    public static void main(String[] args) {
        new StaticTest();
        new StaticTest();
        System.out.println("inside main");
    }
}

class parent {
    static {
        System.out.println("inside parent Static block");
    }
    {
        System.out.println("inside parent initialisation block");
    }

    parent() {
        System.out.println("inside parent constructor");
    }
}

ini memberi

inside parent Static block
inside satic block
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside main

itu seperti menyatakan yang jelas tetapi tampaknya sedikit lebih jelas.


5
2017-07-03 06:36



Kode contoh, yang disetujui sebagai jawaban di sini benar, tetapi saya tidak setuju dengan itu. Itu tidak menunjukkan apa yang sedang terjadi dan saya akan menunjukkan kepada Anda contoh yang baik untuk memahami bagaimana sebenarnya JVM bekerja:

package test;

    class A {
        A() {
            print();
        }

        void print() {
            System.out.println("A");
        }
    }

    class B extends A {
        static int staticVariable2 = 123456;
        static int staticVariable;

        static
        {
            System.out.println(staticVariable2);
            System.out.println("Static Initialization block");
            staticVariable = Math.round(3.5f);
        }

        int instanceVariable;

        {
            System.out.println("Initialization block");
            instanceVariable = Math.round(3.5f);
            staticVariable = Math.round(3.5f);
        }

        B() {
            System.out.println("Constructor");
        }

        public static void main(String[] args) {
            A a = new B();
            a.print();
            System.out.println("main");
        }

        void print() {
            System.out.println(instanceVariable);
        }

        static void somethingElse() {
            System.out.println("Static method");
        }
    }

Sebelum mulai mengomentari kode sumber, saya akan memberi Anda penjelasan singkat tentang variabel statis suatu kelas:

Hal pertama adalah bahwa mereka disebut variabel kelas, mereka termasuk kelas bukan contoh khusus dari kelas. Semua contoh kelas berbagi variabel statis (kelas) ini. Masing-masing dan setiap variabel memiliki nilai default, tergantung pada tipe primitif atau referensi. Hal lain adalah ketika Anda menetapkan kembali variabel statis di beberapa anggota kelas (blok inisialisasi, konstruktor, metode, properti) dan melakukannya Anda mengubah nilai variabel statis bukan untuk contoh tertentu, Anda mengubahnya untuk semua contoh. Untuk menyimpulkan bagian statis, saya akan mengatakan bahwa variabel statis dari suatu kelas tidak diciptakan ketika Anda memulai untuk pertama kalinya kelas, mereka dibuat ketika Anda mendefinisikan kelas Anda, mereka ada di JVM tanpa perlu contoh. Maka akses yang benar anggota statis dari kelas eksternal (kelas di mana mereka tidak didefinisikan) adalah dengan menggunakan nama kelas diikuti oleh titik dan kemudian anggota statis, yang ingin Anda akses (template: <CLASS_NAME>.<STATIC_VARIABLE_NAME>).

Sekarang mari kita lihat kode di atas:

Titik masuk adalah metode utama - hanya ada tiga baris kode. Saya ingin merujuk pada contoh yang saat ini disetujui. Menurutnya hal pertama yang harus dicetak setelah mencetak "Blok Inisialisasi Statis" adalah "Blok Inisialisasi" dan di sini adalah ketidaksetujuan saya, blok inisialisasi non-statis tidak disebut sebelum konstruktor, itu disebut sebelum inisialisasi konstruktor kelas di mana blok inisialisasi didefinisikan. Konstruktor kelas adalah hal pertama yang terlibat ketika Anda membuat objek (contoh kelas) dan kemudian ketika Anda memasukkan konstruktor bagian pertama yang disebut baik implisit (default) super konstruktor atau konstruktor super eksplisit atau panggilan eksplisit ke kelebihan lain konstruktor (tetapi pada titik tertentu jika ada rantai konstruktor yang kelebihan beban, yang terakhir memanggil konstruktor super, secara implisit atau eksplisit).

Ada penciptaan polimorfik suatu objek, tetapi sebelum memasuki kelas B dan metode utamanya, JVM menginisialisasi semua variabel kelas (statis), kemudian berjalan melalui blok inisialisasi statis jika ada dan kemudian memasuki kelas B dan dimulai dengan pelaksanaan metode utama. Ini pergi ke konstruktor kelas B maka segera (implisit) panggilan konstruktor kelas A, menggunakan polimorfisme metode (metode override) yang disebut dalam tubuh konstruktor kelas A adalah yang didefinisikan dalam kelas B dan dalam hal ini variabel bernama instanceVariable digunakan sebelum reinitialization. Setelah menutup konstruktor kelas B, thread dikembalikan ke konstruktor kelas B tetapi pertama-tama pergi ke blok inisialisasi non-statis sebelum mencetak "Constructor". Untuk lebih memahami debug dengan beberapa IDE, saya lebih memilih Eclipse.


3
2018-03-14 13:48



Blok Initializer berisi kode yang selalu dijalankan setiap kali instance dibuat. Ini digunakan untuk menyatakan / menginisialisasi bagian umum dari berbagai konstruktor suatu kelas.

Urutan konstruktor inisialisasi dan blok penginisialisasi tidak masalah, blok initializer selalu dijalankan sebelum konstruktor.

Bagaimana jika kita ingin mengeksekusi kode sekali untuk semua objek dari suatu kelas?

Kami menggunakan Static Block di Java.


1
2017-10-10 09:45



Blok inisialisasi dijalankan setiap kali kelas diinisialisasi dan sebelum konstruktor dipanggil. Mereka biasanya ditempatkan di atas konstruktor di dalam kawat gigi. Anda tidak perlu memasukkannya ke dalam kelas Anda.

Mereka biasanya digunakan untuk menginisialisasi variabel referensi. Ini halaman memberikan penjelasan yang bagus


0
2017-10-21 12:39



Pertanyaannya tidak sepenuhnya jelas, tapi di sini adalah penjelasan singkat tentang cara Anda dapat menginisialisasi data dalam suatu objek. Anggap saja Anda memiliki kelas A yang menyimpan daftar objek.

1) Masukkan nilai awal dalam deklarasi bidang:

class A {
    private List<Object> data = new ArrayList<Object>();
}

2) Tetapkan nilai awal dalam konstruktor:

class A {
    private List<Object> data;
    public A() {
        data = new ArrayList<Object>();
    }
}

Keduanya berasumsi bahwa Anda tidak ingin melewatkan "data" sebagai argumen konstruktor.

Hal-hal menjadi sedikit rumit jika Anda mencampur konstruktor yang kelebihan beban dengan data internal seperti di atas. Mempertimbangkan:

class B {
    private List<Object> data;
    private String name;
    private String userFriendlyName;

    public B() {
        data = new ArrayList<Object>();
        name = "Default name";
        userFriendlyName = "Default user friendly name";
    }

    public B(String name) {
        data = new ArrayList<Object>();
        this.name = name;
        userFriendlyName = name;
    }

    public B(String name, String userFriendlyName) {
        data = new ArrayList<Object>();
        this.name = name;
        this.userFriendlyName = userFriendlyName;
    }
}

Perhatikan bahwa ada banyak kode yang diulang. Anda dapat memperbaiki ini dengan membuat konstruktor memanggil satu sama lain, atau Anda dapat memiliki metode inisialisasi pribadi yang setiap konstruktor panggilan:

class B {
    private List<Object> data;
    private String name;
    private String userFriendlyName;

    public B() {
        this("Default name", "Default user friendly name");
    }

    public B(String name) {
        this(name, name);
    }

    public B(String name, String userFriendlyName) {
        data = new ArrayList<Object>();
        this.name = name;
        this.userFriendlyName = userFriendlyName;
    }
}

atau

class B {
    private List<Object> data;
    private String name;
    private String userFriendlyName;

    public B() {
        init("Default name", "Default user friendly name");
    }

    public B(String name) {
        init(name, name);
    }

    public B(String name, String userFriendlyName) {
        init(name, userFriendlyName);
    }

    private void init(String _name, String _userFriendlyName) {
        data = new ArrayList<Object>();
        this.name = name;
        this.userFriendlyName = userFriendlyName;
    }
}

Keduanya setara (kurang lebih).

Saya harap itu memberi Anda beberapa petunjuk tentang cara menginisialisasi data di objek Anda. Saya tidak akan berbicara tentang blok inisialisasi statis karena itu mungkin agak maju saat ini.

EDIT: Saya telah menafsirkan pertanyaan Anda sebagai "bagaimana cara menginisialisasi variabel instan saya", bukan "bagaimana cara kerja blok inisiserator" sebagai blok inisialisasi adalah konsep yang relatif maju, dan dari nada pertanyaan tampaknya Anda bertanya tentang konsep yang lebih sederhana. Saya bisa salah.


0
2017-10-21 12:45