Memanggil metode Java tanpa nama

101

Saya melihat kode di bawah ini dan menemukan sesuatu yang agak aneh:

public class Sequence {
    Sequence() {
        System.out.print("c ");
    }

    {
        System.out.print("y ");
    }

    public static void main(String[] args) {
        new Sequence().go();
    }

    void go() {
        System.out.print("g ");
    }

    static {
        System.out.print("x ");
    }
}

Saya akan mengharapkan ini untuk memberikan kesalahan kompilasi karena System.outdengan "y" bukan milik deklarasi metode hanya a { }. Mengapa ini valid? Saya tidak melihat bagaimana kode ini akan atau harus dipanggil.

Saat menjalankan ini, ia x y c gjuga menghasilkan , mengapa static { }get dipanggil sebelum konstruktor urutan?

david99world
sumber

Jawaban:

149

Ini:

static {
        System.out.print("x ");
    }

adalah blok inisialisasi statis , dan dipanggil saat kelas dimuat. Anda dapat memiliki sebanyak mungkin dari mereka di kelas Anda yang Anda inginkan, dan mereka akan dieksekusi dalam urutan penampilannya (dari atas ke bawah).

Ini:

    {
        System.out.print("y ");
    }

adalah blok inisialisasi , dan kode disalin ke awal setiap konstruktor kelas. Jadi, jika Anda memiliki banyak konstruktor kelas Anda, dan mereka semua perlu melakukan sesuatu yang umum di awal, Anda hanya perlu menulis kode sekali dan meletakkannya di blok inisialisasi seperti ini.

Oleh karena itu, keluaran Anda sangat masuk akal.

Seperti yang dikomentari Stanley di bawah ini, lihat bagian dalam tutorial Oracle yang menjelaskan blok inisialisasi untuk informasi lebih lanjut.

jlordo
sumber
12
Jawaban yang bagus. Cari tahu lebih lanjut tentang blok inisialisasi di http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
Stanley
6
the code is copied into the beginning of each constructor of the class- ini tidak benar. Katakanlah konstruktor dimulai dengan super("x ");, konstruktor super akan mengeksekusi sebelum blok inisialisasi apa pun.
RokL
3
ya, panggilan implisit dan eksplisit ke superkonstruktor akan dijalankan terlebih dahulu, blok inisialisasi berikutnya, dan daripada kode konstruktor lainnya.
jlordo
25

Ini bukan metode tapi blok inisialisasi .

 {
    System.out.print("y ");
 }

Ini akan dijalankan sebelum panggilan konstruktor. Sementara

static {
        System.out.print("x ");
       }

adalah blok inisialisasi statis yang dijalankan ketika kelas dimuat oleh pemuat kelas.

Jadi ketika Anda menjalankan kode Anda
1. Kelas dimuat oleh loader kelas sehingga blok inisialisasi statis dijalankan
Output: x dicetak
2. Objek dibuat sehingga blok inisialisasi dijalankan dan kemudian konstuktor disebut
Output: y dicetak diikuti oleh c
3. Metode utama dipanggil yang pada gilirannya memanggil metode go
Output: g dicetak

Hasil akhir: xycg
Ini mungkin membantu http://blog.sanaulla.info/2008/06/30/initialization-blocks-in-java/

xyz
sumber
@Cthulhu: Terima kasih. Itu berlaku sampai minggu lalu saya telah memperbaruinya dengan tautan baru.
xyz
16

Itu adalah blok inisialisasi instance yang diikuti dengan blok inisialisasi statis .

{
    System.out.print("y ");
}

dipanggil saat Anda membuat instance kelas.

static {
    System.out.print("x ");
}

dipanggil saat kelas dimuat oleh pemuat kelas. Jadi, saat Anda melakukannya

new Sequence().go();

kelas tersebut dimuat, jadi ia mengeksekusi static {}, lalu mengeksekusi blok inisialisasi instance {}, kemudian badan konstruktor dipanggil, dan kemudian metode pada instance yang baru dibuat. Ergo hasilnya x y c g.

Luchian Grigore
sumber
15
static {
        System.out.print("x ");
    }

Merupakan blok statis dan dipanggil selama Class Loading

{
    System.out.print("y ");
}

Merupakan blok inisialisasi

Anda dapat memiliki beberapa blok inisialisasi dalam sebuah kelas yang akan dieksekusi sesuai urutan kemunculannya di kelas tersebut.

Perhatikan bahwa setiap blok inisialisasi yang ada di kelas dijalankan sebelum konstruktor.

Narendra Pathai
sumber
10
static {
      System.out.print("x ");
}

adalah blok inisialisasi yang dibagikan oleh kelas (seperti yang ditunjukkan oleh static), yang dieksekusi terlebih dahulu.

{
        System.out.print("y ");

}

adalah blok inisialisasi yang dibagikan oleh semua objek (konstruktor) kelas, yang muncul berikutnya.

Sequence() {
        System.out.print("c ");
}

adalah konstruktor khusus untuk kelas, yang dijalankan ketiga. Blok inisialisasi instance dipanggil pertama kali setiap kali konstruktor dijalankan. Itulah mengapa "y" muncul sebelum "c".

void go() {
        System.out.print("g ");
}

hanyalah metode instance yang terkait dengan objek yang dibangun menggunakan konstruktor di atas, yang datang terakhir.

Terry Li
sumber
9
{
    System.out.print("y ");
}

Jenis blok ini disebut initializer block. Ini dijalankan setiap kali Anda membuat instance dari a class. Pada waktu kompilasi, kode ini dipindahkan ke setiap konstruktor kelas Anda.

Sedangkan dalam kasus static initializerblok: -

static {
    System.out.println("x ");
}

itu dijalankan sekali ketika kelas dimuat. Kami biasanya menggunakan staticblok penginisialisasi ketika inisialisasi staticbidang, memerlukan beberapa langkah.

Rohit Jain
sumber
6

Ini digunakan sebagai blok inisialisasi dan berjalan setelah deklarasi statis apa pun . Ini bisa digunakan untuk memastikan bahwa tidak ada orang lain yang dapat membuat instance kelas (Dengan cara yang sama Anda akan menggunakan konstruktor pribadi) seperti dengan pola desain Singleton .

maloney
sumber
3
static {
    System.out.print("x ");
}

Static blockshanya dijalankan sekali ketika kelas dimuat dan diinisialisasi oleh JRE.

Dan non-staticblok akan dipanggil setiap kali Anda membuat instance baru dan itu akan dipanggil tepat sebelum Pembuat.

Seperti di sini Anda telah membuat hanya 1 contoh dari Sequencejadi dibangun telah dipanggil setelah non-staticblok dan kemudian metode yang sebenarnya tujuan Anda.

Subhrajyoti Majumder
sumber