Java: Statik bir başlatma bloğu ne zaman faydalıdır?


91

Bir staticblok içinde başlatma arasındaki fark nedir :

public class staticTest {

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

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

Ve bireysel statik başlatma:

public class staticTest {

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

    ....

1
Yalnızca statik başlatma bloğundaki atamaları kullanıyorsunuz, bu nedenle elbette bunlar statik değişken ataması kullanılarak yapılabilir. Atama dışı ifadeler yürütmeniz gerekirse ne olacağını görmeyi denediniz mi?
Platinum Azure

Sınıfları yüklemek veya yerel kitaplığı yüklemek için iyi bir yerdir.
qrtt1

1
Statik değişkenlerden kaçınılması gerektiğini ve bu nedenle statik başlatma bloklarının genellikle iyi bir fikir olmadığını unutmayın. Kendinizi onları çok kullanırken bulursanız, bazı sorunlar bekleyin.
Bill K

Yanıtlar:


106

Statik bir başlatma blokları, örneğin koşulların kullanılması gibi daha karmaşık başlatmaya izin verir:

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

Veya sadece inşaattan daha fazlası gerekli olduğunda: Örneğinizi oluşturmak için bir oluşturucu kullanırken, istisna işleme veya statik alanlar oluşturmaktan başka çalışma gereklidir.

Statik bir başlatma bloğu ayrıca satır içi statik başlatıcılardan sonra çalışır, bu nedenle aşağıdakiler geçerlidir:

static double a;
static double b = 1;

static {
    a = b * 4; // Evaluates to 4
}

3
"B = a * 4;" yapmak satır içi yalnızca, b'nin a'dan önce bildirilmesi durumunda sorun olur, sizin örneğinizde durum böyle değildir.
George Hawkins

1
@GeorgeHawkins Sadece statik bir başlatıcının satır içi başlatıcılardan sonra çalıştığını göstermeye çalışıyordum, bir eşdeğerin satır içi yapılamayacağını değil. Bununla birlikte, senin fikrini alıyorum ve örneği (umarım) daha net olacak şekilde güncelledim.
Rich O'Kelly

1
Sırf eğlence olsun diye, ilk örneğinizin aynı kolaylıkla "statik çift a = bir Koşul? 0: 1;" olabileceğini belirtebilirim. Örneklerinizin harika olmadığından değil, sadece söylüyorum ... :)
Bill K

18

Tipik bir kullanım:

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

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

Statik başlatıcı olmadan bunu nasıl yapardınız?


2
Cevap: Guava :) +1
Paul Bellora

2
Ek kitaplıklar olmadan başka bir cevap: SETdeğişken başlatıcı ( private final static Set<String> SET = createValueSet()) ' nın başlatılmasını kapsayan statik bir yöntem oluşturun ve bunu kullanın . Ya 5 setiniz ve 2 haritanız varsa, hepsini tek bir staticbloğa atar mıydınız?
TWiStErRob

14

Try / catch bloğunu static{}aşağıdaki gibi kullanabilirsiniz :

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);
        }

    }
}

Not: gelen Tavsiye bu !


11

Başlatma sırasında istisna işleme başka bir nedendir. Örneğin:

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

Bu, yukarıdaki gibi kontrol edilen istisnaları can sıkıcı bir şekilde atan kurucular için veya istisnaya yatkın olabilecek daha karmaşık başlatma mantığı için kullanışlıdır.


5

Bazen statik değişkenlere değer atamaktan daha fazlasını yapmak istersiniz. Sınıf gövdesine rastgele ifadeler koyamayacağınız için, statik bir başlatıcı bloğu kullanabilirsiniz.


4

Örneğinizde hiçbir fark yok; ancak genellikle başlangıç ​​değeri, tek bir ifadede rahatça ifade edilenden daha karmaşıktır (örneğin, List<String>içeriği en iyi bir for-döngü ile ifade edilen bir değerdir; veya Methodmevcut olmayabilir, bu nedenle istisna işleyicilere ihtiyaç vardır) ve / veya statik alanların belirli bir sırada ayarlanması gerekir.


4

staticblok, senkronize yöntem kullanılmasını önlemek için tekli örneği başlatmak için kullanılabilir . getInstance()


3

Teknik olarak, onsuz kurtulabilirsin. Bazıları çok satırlı başlatma kodunu statik bir yönteme geçmek için tercih eder. Nispeten basit multistatement başlatma için statik bir başlatıcı kullanmaktan oldukça memnunum.

Tabii ki, neredeyse her zaman statiğimi yapar finalve değiştirilemez bir nesneye işaret ederdim .


3

Statik anahtar kelime (ister değişken ister blok olsun) sınıfa aittir. Yani sınıf çağrıldığında, bu değişkenler veya bloklar çalıştırılır. Bu nedenle, başlatma işlemlerinin çoğu statik anahtar kelime yardımıyla yapılacaktır. Sınıfın kendisine ait olduğu için, sınıfın bir örneğini oluşturmadan ona doğrudan erişebilir.

Bir örnek verelim, Renk, beden, marka vb. Gibi çeşitli değişkenlerin olduğu bir ayakkabı sınıfı var ... Ve burada ayakkabı üreten firmanın tek bir markası varsa, onu statik bir değişken olarak başlatmalıyız. Dolayısıyla, ayakkabı sınıfı çağrıldığında ve farklı ayakkabı türleri üretildiğinde (sınıfın bir örneği oluşturularak) o sırada renk ve beden hafızayı her yeni ayakkabı oluşturulduğunda kaplayacaktır, ancak burada marka tüm ayakkabılar için ortak bir özelliktir, böylece kaç ayakkabı üretilirse üretilsin bir kez hafızayı kaplayacak.

Misal:

    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("=================");
    }
}

1

Örnek değişkenlerimizi (statik olmayan değişkenler, sınıfa değil nesnelere ait değişkenler) başlatmak için yapıcılar kullanırız.

Sınıf değişkenlerini (statik değişkenler) başlatmak ve bunu bir nesne oluşturmadan yapmak istiyorsanız (yapıcılar yalnızca bir nesne oluştururken çağrılabilir), o zaman statik bloklara ihtiyacınız vardır.

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);
    }
}

Stdin'i statik bir başlatıcıda okumak oldukça kötü bir fikir. Ve System.out.println("B * H");oldukça faydasız. Ve cevabın kendisi oldukça belirsiz. OP, kuruculardan veya örnek değişkenlerinden bahsetmedi.
shmosel

Bu, statik başlatıcının ne olduğunu ve nasıl kullanıldığını gösteren bir örnektir. OP yapıcılar veya örnek değişkenleri istemedi, ancak ona statik başlatıcının yapıcıdan farkını öğretmek için bunu bilmesi gerekiyor. Aksi takdirde, "Neden statik değişkenlerimi başlatmak için sadece bir kurucu kullanmıyorum?"
Michael

0

Statik kod bloğu, alanların başlangıçtan daha fazlasına sahip olmasını, alanları farklı bir bildirim sırasına göre başlatmayı ve ayrıca koşullu ilkleştirme için kullanılabilmesini sağlar.

Daha spesifik olarak,

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

çalışmayacaktır çünkü a ve b, ab'den sonra bildirilmiştir.

Ancak statik bir init kullanabilirim. bunun üstesinden gelmek için engelleyin.

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;
}

3
Söyledikleriniz doğru olsa da, statik başlatıcı bloğunun gerekliliğini göstermez. abBeyannamenizi beyanının altına taşıyabilirsiniz b.
gawi

0

Statik bir başlatma bloğu, sınıfın ilk kullanımından önce belirtilen sınıf statik türlerini başlatmak istiyorsanız kullanışlıdır. Sonraki kullanım herhangi bir statik başlatma bloğunu çağırmayacaktır. Örnek üyelerini başlatan örnek başlatıcıların tam tersidir.


0

Sınıf yükleme süresi sırasında belirli bir ifadeyi değerlendirmek istediğinizde, statik bloktan yararlanabilirsiniz ancak unutmayın:

Statik bloktaki bir istisnayı işlemeniz gerekir, yani statik bir bloktan bir istisna atamazsınız.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.