Java: Kapan blok inisialisasi statis berguna?

91

Apa perbedaan antara inisialisasi dalam satu staticblok:

public class staticTest {

    static String s;
    static int n;
    static double d;

    static {
        s = "I'm static";
        n = 500;
        d = 4000.0001;
    }
    ...

Dan inisialisasi statis individu:

public class staticTest {

    static String s = "I'm static";
    static int n    = 500;
    static double d = 4000.0001;

    ....
Adam Matan
sumber
1
Anda hanya menggunakan tugas di blok inisialisasi statis, jadi tentu saja itu bisa dilakukan menggunakan tugas variabel statis. Sudahkah Anda mencoba melihat apa yang terjadi jika Anda perlu menjalankan pernyataan non-penugasan?
Platinum Azure
Ini adalah tempat yang baik untuk memuat kelas atau memuat perpustakaan asli.
qrtt1
1
Perhatikan bahwa variabel statis harus dihindari dan oleh karena itu blok inisialisasi statis umumnya bukan ide yang bagus. Jika Anda menemukan diri Anda sering menggunakannya, nantikan beberapa masalah di telepon.
Bill K

Jawaban:

106

Blok inisialisasi statis memungkinkan inisialisasi yang lebih kompleks, misalnya menggunakan kondisional:

static double a;
static {
    if (SomeCondition) {
      a = 0;
    } else {
      a = 1;
    }
}

Atau jika lebih dari sekadar konstruksi diperlukan: saat menggunakan pembuat untuk membuat instance Anda, penanganan pengecualian atau pekerjaan selain membuat bidang statis diperlukan.

Blok inisialisasi statis juga berjalan setelah penginisialisasi statis sebaris, jadi berikut ini valid:

static double a;
static double b = 1;

static {
    a = b * 4; // Evaluates to 4
}
Rich O'Kelly
sumber
3
Melakukan "b = a * 4;" inline hanya akan menjadi masalah jika b dideklarasikan sebelum a, yang tidak terjadi dalam contoh Anda.
George Hawkins
1
@GeorgeHawkins Saya hanya mencoba menggambarkan bahwa penginisialisasi statis berjalan setelah penginisialisasi inline, bukan bahwa persamaan tidak dapat dilakukan secara inline. Namun, saya mengambil poin Anda dan telah memperbarui contoh menjadi (semoga) menjadi lebih jelas.
Rich O'Kelly
1
Hanya untuk bersenang-senang, saya dapat menunjukkan bahwa contoh pertama Anda dapat dengan mudah menjadi "static double a = someCondition? 0: 1;" Bukan karena teladan Anda tidak bagus, saya hanya mengatakan ... :)
Bill K
18

Penggunaan tipikal:

private final static Set<String> SET = new HashSet<String>();

static {
    SET.add("value1");
    SET.add("value2");
    SET.add("value3");
}

Bagaimana Anda melakukannya tanpa penginisialisasi statis?

gawi
sumber
2
Jawaban: Jambu :) +1
Paul Bellora
2
Jawaban lain tanpa pustaka tambahan: buat metode statis yang merangkum inisialisasi SETdan menggunakan variabel penginisialisasi ( private final static Set<String> SET = createValueSet()). Bagaimana jika Anda memiliki 5 set dan 2 peta, apakah Anda akan membuang semuanya ke dalam satu staticblok?
TWiStErRob
14

Anda dapat menggunakan blok try / catch di dalam static{}seperti di bawah ini:

MyCode{

    static Scanner input = new Scanner(System.in);
    static boolean flag = true;
    static int B = input.nextInt();
    static int H = input.nextInt();

    static{
        try{
            if(B <= 0 || H <= 0){
                flag = false;
                throw new Exception("Breadth and height must be positive");
            }
        }catch(Exception e){
            System.out.println(e);
        }

    }
}

PS: Disebut dari ini !

karan patel
sumber
11

Penanganan pengecualian selama inisialisasi adalah alasan lain. Sebagai contoh:

static URL url;
static {
    try {
        url = new URL("https://blahblah.com");
    }
    catch (MalformedURLException mue) {
        //log exception or handle otherwise
    }
}

Ini berguna untuk konstruktor yang secara mengganggu menampilkan pengecualian yang dicentang, seperti di atas, atau logika inisialisasi yang lebih kompleks yang mungkin rentan terhadap pengecualian.

Paul Bellora
sumber
5

Terkadang Anda ingin melakukan lebih dari sekadar menetapkan nilai ke variabel statis. Karena Anda tidak bisa meletakkan pernyataan arbitrer di badan kelas, Anda bisa menggunakan blok penginisialisasi statis.

Jesper
sumber
4

Dalam contoh Anda, tidak ada perbedaan; tetapi seringkali nilai awal lebih kompleks daripada yang diekspresikan dengan nyaman dalam ekspresi tunggal (misalnya, itu adalah List<String>yang isinya paling baik diekspresikan dengan for-loop; atau itu Methodmungkin tidak ada, jadi diperlukan penangan pengecualian), dan / atau bidang statis perlu disetel dalam urutan tertentu.

ruakh
sumber
4

staticblok dapat digunakan untuk menginisialisasi contoh tunggal , untuk mencegah penggunaan metode tersinkronisasi getInstance() .

Pelaut Danubian
sumber
3

Secara teknis, Anda bisa lolos tanpanya. Beberapa lebih memilih kode inisialisasi multiline untuk menggunakan metode statis. Saya cukup senang menggunakan penginisialisasi statis untuk inisialisasi multistatement yang relatif sederhana.

Tentu saja, saya hampir selalu membuat statika saya finaldan menunjuk ke objek yang tidak dapat dimodifikasi.

Tom Hawtin - tackline
sumber
3

Kata kunci statis (apakah itu variabel atau blok) adalah milik kelas. Jadi ketika kelas dipanggil, variabel atau blok ini dijalankan. Jadi sebagian besar inisialisasi akan dilakukan dengan bantuan kata kunci statis. Karena ini adalah milik kelas itu sendiri, kelas tersebut dapat langsung mengaksesnya, tanpa membuat instance kelas.

Mari kita ambil contoh, Ada kelas sepatu yang didalamnya terdapat beberapa variabel seperti warna, ukuran, merek dll. Dan disini jika perusahaan pembuat sepatu hanya mempunyai satu merek maka kita harus menginisialisasi sebagai variabel statis. Jadi, ketika kelas sepatu dipanggil dan berbagai jenis sepatu diproduksi (dengan membuat instance kelas) pada saat itu warna dan ukuran akan menempati memori setiap kali sepatu baru dibuat, tetapi di sini merek adalah properti bersama untuk semua sepatu, sehingga akan menempati memori sekali tidak peduli berapa banyak sepatu yang diproduksi.

Contoh:

    class Shoe {
    int size;
    String colour;
    static String brand = "Nike";

    public Shoe(int size, String colour) {
        super();
        this.size = size;
        this.colour = colour;
    }

    void displayShoe() {
        System.out.printf("%-2d %-8s %s %n",size,colour, brand);
    }

    public static void main(String args[]) {
        Shoe s1 = new Shoe(7, "Blue");
        Shoe s2 = new Shoe(8, "White");

        System.out.println("=================");
        s1.displayShoe();
        s2.displayShoe();
        System.out.println("=================");
    }
}
orang bodoh
sumber
1

Kami menggunakan konstruktor untuk menginisialisasi variabel instan kami (variabel non-statis, variabel milik objek, bukan kelas).

Jika Anda ingin menginisialisasi variabel kelas (variabel statis) dan ingin melakukannya tanpa membuat objek (konstruktor hanya dapat dipanggil saat membuat objek), Anda memerlukan blok statis.

static Scanner input = new Scanner(System.in);
static int widht;
static int height;

static
{
    widht = input.nextInt();
    input.nextLine();
    height = input.nextInt();
    input.close();

    if ((widht < 0) || (height < 0))
    {
        System.out.println("java.lang.Exception: Width and height must be positive");
    }
    else
    {
        System.out.println("widht * height = " + widht * height);
    }
}
Michael
sumber
Membaca stdin di penginisialisasi statis adalah ide yang cukup buruk. Dan System.out.println("B * H");sangat tidak berguna. Dan jawabannya sendiri sangat tidak jelas. OP tidak menyebutkan konstruktor atau variabel instan.
shmosel
Ini hanyalah sebuah contoh yang menunjukkan apa itu penginisialisasi statis dan bagaimana ia digunakan. OP tidak meminta konstruktor atau variabel instan tetapi untuk mengajari dia perbedaan penginisialisasi statis dari konstruktor dia perlu mengetahuinya. Jika tidak, dia akan berkata "Mengapa saya tidak menggunakan konstruktor untuk menginisialisasi variabel statis saya?"
Michael
0

Blok kode statis memungkinkan untuk menginisialisasi field dengan lebih dari sekedar instuction, menginisialisasi field dalam urutan deklarasi yang berbeda dan juga dapat digunakan untuk inisialisasi bersyarat.

Lebih spesifik,

static final String ab = a+b;
static final String a = "Hello,";
static final String b = ", world";

tidak akan berfungsi karena a dan b dideklarasikan setelah ab.

Namun saya bisa menggunakan init statis. blokir untuk mengatasi ini.

static final String ab;
static final String a;
static final String b;

static {
  b = ", world";
  a = "Hello";
  ab = a + b;
}

static final String ab;
static final String a;
static final String b;

static {
  b = (...) ? ", world" : ", universe";
  a = "Hello";
  ab = a + b;
}
algolicious
sumber
3
Meskipun apa yang Anda katakan itu benar, itu tidak menunjukkan perlunya blok penginisialisasi statis. Anda bisa memindahkan abdeklarasi Anda di bawah deklarasi b.
gawi
0

Blok inisialisasi statis berguna jika Anda ingin menginisialisasi jenis statis kelas yang ditentukan, sebelum kelas pertama digunakan. Penggunaan selanjutnya tidak akan memanggil blok inisialisasi statis apa pun. Ini kebalikan langsung dari penginisialisasi instance, yang menginisialisasi anggota instance.

Remario
sumber
0

Ketika Anda ingin mengevaluasi ekspresi tertentu saat waktu pemuatan kelas maka Anda dapat menggunakan blok statis tetapi ingat:

Anda harus menangani pengecualian dalam blok statis yang berarti Anda tidak dapat membuat pengecualian dari blok statis.

Saya_Pratik
sumber