Bekerja dengan konstruktor statis di Jawa

11

Saya tidak mendapatkan pemahaman lengkap tentang konstruktor statis di Jawa. Jika diizinkan, mengapa diizinkan? Dalam skenario apa Anda akan menggunakannya? Apa tujuannya? Bisakah seseorang memberi saya contoh sederhana?

Kapeel45
sumber
2
Berbagi penelitian Anda membantu semua orang. Beri tahu kami apa yang telah Anda coba dan mengapa itu tidak memenuhi kebutuhan Anda. Ini menunjukkan bahwa Anda telah meluangkan waktu untuk mencoba membantu diri sendiri, itu menyelamatkan kami dari mengulangi jawaban yang jelas, dan yang paling utama itu membantu Anda mendapatkan jawaban yang lebih spesifik dan relevan. Lihat juga Cara Meminta
nyamuk
3
Tidak ada yang namanya "konstruktor statis".
David Conrad

Jawaban:

28

Sebenarnya, Java tidak memiliki konstruktor statis karena konstruktor, menurut definisi, tidak boleh statis. Apa yang Anda maksud disebut "blok inisialisasi statis." Konstruktor menyiratkan bahwa Anda membangun objek. Anda tidak dapat memiliki konstruktor untuk kelas karena kelas bukan turunan dari kelas itu sendiri. Ini hanyalah sebuah kelas. Hal yang "membangun" kelas disebut kompiler (atau mesin virtual, tergantung pada apa yang dimaksud dengan "konstruksi"), dan jika Anda masuk ke membangun kode dalam kode lain, Anda masuk ke pembuatan kode, yang merupakan binatang yang sama sekali berbeda.

Semua samping, nit, blok inisialisasi statis digunakan untuk menginisialisasi bidang statis (atau tingkat kelas) kompleks untuk kelas. Biasanya ini digunakan untuk menginisialisasi hal-hal yang tidak dapat diinisialisasi dalam satu baris, atau mengharuskan beberapa objek lain (yang mungkin atau mungkin tidak ada di kelas di mana blok statis diimplementasikan) diinisialisasi terlebih dahulu.

Pada dasarnya, seseorang dapat menggunakannya untuk memberi tahu kelas "Hei, atur variabel A ke nilai ini PERTAMA, lalu, setelah selesai, gunakan nilai A untuk menginisialisasi B." Karena Java mengharuskan inisialisasi bidang standar dilakukan baik di dalam konstruktor atau metode, atau melalui panggilan konstruktor atau metode (kecuali itu adalah literal), ini dapat menjadi metode yang nyaman untuk menginisialisasi objek yang kompleks dan statis.

Blok inisialisasi statis tidak terlalu sering dibutuhkan, dan umumnya harus dihindari kecuali mereka benar - benar digunakan. Jangan salah, mereka memiliki tempat di Jawa, tetapi seperti banyak hal lain (seperti pernyataan break, return, switch, dan goto) mereka dapat dengan mudah digunakan, yang mengurangi keterbacaan dan pemeliharaan kode. -Basis mereka digunakan dalam.

Contoh singkat dari blok inisialisasi statis yang digunakan adalah sebagai berikut (sesuai dengan penjelasan yang sangat baik dari blok inisialisasi statis yang ditemukan di sini ):

Kode:

public class StaticExample{
    static {
        System.out.println("This is first static block");
    }

    public StaticExample(){
        System.out.println("This is constructor");
    }

    public static String staticString = "Static Variable";

    static {
        System.out.println("This is second static block and "
                                                    + staticString);
    }

    public static void main(String[] args){
        StaticExample statEx = new StaticExample();
        StaticExample.staticMethod2();
    }

    static {
        staticMethod();
        System.out.println("This is third static block");
    }

    public static void staticMethod() {
        System.out.println("This is static method");
    }

    public static void staticMethod2() {
        System.out.println("This is static method2");
    }
}    

Keluaran:

This is first static block
This is second static block and Static Variable
This is static method
This is third static block
This is constructor
This is static method2

Beberapa contoh mereka daftar ketika blok statis dapat berguna:

  • Jika Anda memuat driver dan item lain ke namespace. Sebagai contoh, kelas Kelas memiliki blok statis di mana ia mendaftarkan penduduk asli.
  • Jika Anda perlu melakukan perhitungan untuk menginisialisasi variabel statis Anda, Anda dapat mendeklarasikan blok statis yang dijalankan tepat sekali, ketika kelas dimuat pertama kali.
  • Masalah terkait keamanan atau tugas terkait pencatatan

Beberapa alasan untuk TIDAK menggunakan blok statis (dalam situasi lain):

  • Ada batasan JVM bahwa blok penginisialisasi statis tidak boleh melebihi 64K.
  • Anda tidak dapat membuang Pengecualian yang Dicentang.
  • Anda tidak dapat menggunakan thiskata kunci karena tidak ada contoh.
  • Anda tidak boleh mencoba mengakses super karena tidak ada hal seperti itu untuk blok statis.
  • Anda seharusnya tidak mengembalikan apa pun dari blok ini.
  • Blok statis membuat pengujian mimpi buruk.

Saya harus perhatikan: Walaupun beberapa bahasa (seperti C #) mungkin memiliki sintaks untuk "konstruktor" yang statis, "konstruktor" itu berfungsi seperti halnya blok inisialisasi statis di Jawa, dan dilihat oleh banyak orang (termasuk saya) sebagai misnomers dalam bahasa, diberikan konsep dasar konstruktor OOP .

Gurgadurgen
sumber
tautan tentang blok statis tidak berfungsi lagi
ASh
5

digunakan untuk menginisialisasi bidang yang lebih sulit daripada hanya menugaskannya:

public class Example{

    public final static Map<String, String> preFilledField;

    static{
        Map<String, String> tmp = new HashMap<>();
        //fill map
        preFilledField = Collections.unmodifiableMap(tmp);
    }
}

tidak mungkin untuk mengisi peta pada inisialisasi (kecuali jika Anda menggunakan hack subclass anonim) jadi ini adalah cara terbaik untuk menjamin itu diisi sebelum digunakan pertama kali

Anda juga dapat melakukan ini untuk menangkap pengecualian yang diperiksa saat inisialisasi

aneh ratchet
sumber
Ini sangat banyak salah satu kegunaan utama yang telah saya lihat tetapi dengan dimasukkannya metode pabrik statis untuk kerangka koleksi di Jawa 9 kasus penggunaan ini benar-benar telah ditinggalkan dengan cara.
Hangman4358
2

Jawaban Gurgadurgen mungkin adalah yang Anda cari, tetapi saya hanya akan menambahkan beberapa poin lain yang kadang-kadang diabaikan ketika seseorang menginginkan "konstruktor statis".

Jika Anda menginginkan metode statis yang membuat instance kelas Anda, Anda bisa membuat metode statis yang hanya memanggil konstruktor kelas.

public class Example
{
    /** Static method to create an instance. */
    public static Example build()
    { return new Example() ; }

    /** A field of each instance. */
    private String stuff ;

    /** The class's actual constructor. */
    public Example()
    { stuff = new String() ; }

    public String getStuff()
    { return this.stuff ; }

    /**
     * Mutator for "stuff" property. By convention this returns "void"
     * but you might want to return the object itself, to support the
     * sort of chained invocations that are becoming trendy now. You'll
     * see the stylistic benefits of chaining later in this example.
     */
    public Example setStuff( String newStuff )
    {
        this.stuff = newStuff ;
        return this ;
    }
}

public class ExampleTest
{
    public static void main( String[] args )
    {
        // The usual instance model.
        Example first = new Example() ;
        System.out.println( first.setStuff("stuff").getStuff() ) ;

        // Using your static method to construct an instance:
        Example second = Example.build() ;
        System.out.println( second.setStuff("more stuff").getStuff() ) ;

        // Chaining all the invocations at once:
        System.out.println( Example.build().setStuff("even more stuff").getStuff() ) ;
    }
}

Ini menghasilkan output:

stuff
more stuff
even more stuff

Alasan lain untuk membuat metode statis untuk membangun sebuah instance adalah kasus ketika Anda ingin memastikan bahwa tepat satu instance dari kelas Anda ada pada waktu tertentu; ini disebut singleton . Dengan konvensi, kelas semacam itu akan menyediakan metode statis yang dipanggil getInstance()untuk mendapatkan satu-satunya instance yang diperlakukan sebagai "singleton".

public class SingletonExample extends Example
{
    // Note: This extends my previous example, which has a "stuff"
    // property, and a trivial constructor.

    /** The singleton instance, statically initialized as null. */
    private static SingletonExample singleton = null ;

    /**
     * The static accessor for the singleton. If no instance exists,
     * then it will be created; otherwise, the one that already exists
     * will be returned.
     */
    public static SingletonExample getInstance()
    {
        if( singleton == null )
            singleton = new SingletonExample() ;
        return singleton ;
    }
}

public class SingletonExampleTest
{
    public static void main( String[] args )
    {
        System.out.println( SingletonExample.getInstance().setStuff("stuff").getStuff() ) ;

        // You could still create instances of this class normally if you want to.
        SingletonExample otherstuff = new SingletonExample() ;
        otherstuff.setStuff("other stuff") ;

        // But watch what happens to this.
        System.out.println( SingletonExample.getInstance().getStuff() ) ;
        System.out.println( otherstuff.getStuff() ) ;

        // Now we show what happens when you start modifying the singleton.
        SingletonExample theoneandonly = SingletonExample.getInstance() ;
        theoneandonly.setStuff("changed stuff") ;
        System.out.println( SingletonExample.getInstance().getStuff() ) ;
    }
}

Ini menghasilkan yang berikut ini.

stuff
stuff
other stuff
changed stuff

Dengan menyimpan referensi ke singleton, dan kemudian memodifikasinya, panggilan selanjutnya untuk getInstance()mendapatkan singleton yang dimodifikasi itu.

Sangat menggoda untuk menggunakan lajang sebagai cara untuk mulai membuat variabel global untuk aplikasi Anda. Dalam beberapa konteks ini bisa berguna, tetapi juga bisa membuat Anda kesulitan. Secara khusus saya mengalami bug yang menarik saat mengembangkan aplikasi Android, di mana contoh tunggal bisa hilang. Melompat dari satu aktivitas ke aktivitas lain terkadang dapat mengarahkan JVM untuk menggunakan "kelas pemuat" baru yang tidak akan tahu tentang singleton yang disimpan secara statis oleh pemuat kelas sebelumnya.

zerobandwidth
sumber
0

Sementara saya mengerti bahwa ada banyak orang yang melihat gagasan "konstruktor statis" sebagai istilah yang keliru, saya tidak percaya itu yang terjadi. Masalahnya adalah dalam proses membangun kelas dan objek instance mereka . Telah dinyatakan di utas lain bahwa konstruksi kelas adalah pekerjaan kompilator. Bahkan di Jawa, ini hanya setengah benar.

Compiler membuat scaffold untuk setiap definisi kelas. Scaffold berisi metadata tentang kelas dan contoh apa yang harus ada di dalamnya pada saat konstruksi. Jika kelas mendefinisikan bidang yang diberi nilai primitif konstan, maka nilai itu termasuk dalam scaffold oleh kompiler. Untuk jenis nilai lain yang ditugaskan, kompiler menghasilkan rutin inisialisasi yang harus dijalankan 1 kali, sebelum pembuatan instance kelas pertama, yang memperbarui perancah dengan nilai yang tepat. Pembaruan ini tidak dapat dilakukan oleh kompiler.

Karena pembaruan satu kali ini untuk perancah sering merupakan prasyarat penting untuk berfungsinya konstruktor instance, juga masuk akal untuk menyebutnya jenis konstruktor. Inilah sebabnya mengapa dalam bahasa OO umum yang mendukung konsep, itu disebut konstruktor statis. Konsep di balik blok inisialisasi statis di Jawa adalah sedikit lebih dari perubahan semantik untuk tetap sejalan dengan gagasan bahwa seorang programmer Java harus menjadi sistem dan implementasi agnostik.

Arkain
sumber
0

Seperti jawaban lain katakan, Anda dapat menulis metode statis yang membangun objek. Ini mengatasi kurangnya konstruktor bernama di Jawa (dan banyak bahasa lainnya. Delphi mendukung konstruktor bernama). Anda dapat bermain dengan tipe dan urutan parameter tetapi ini dapat menyebabkan kode tidak jelas dan rapuh.

Misalnya, kami dapat membuat skenario di mana objek Anda dapat dibangun dari string XML atau string JSON. Anda dapat menulis metode seperti:

static MyObject createFromXml(String xml);
static MyObject createFromJson(String json);

Saya sering menggunakan ini sebagai alternatif untuk konstruktor tanpa parameter dengan metode inisialisasi bernama:

MyObject myObject = new MyObject();
myObject.loadXml(xml). 

Anda bisa melihat metode pembuatan statis sebagai menerapkan pola pembangun di dalam kelas Anda.

kiwiron
sumber
Ketika saya membaca pertanyaan, ini tentang inisialisasi statis, bukan tentang emthod statis normal.
CodesInChaos
-2

Anda dapat melihat bagian "statis" seperti yang digunakan konstruktor tingkat kelas untuk menginisialisasi properti kelas (statis di java). Sama seperti konstruktor "normal" yang digunakan untuk menginisialisasi properti tingkat instance.

AlfredoCasado
sumber