Statik sınıf başlatma ne zaman gerçekleşir?


110

Statik alanlar ne zaman başlatılır? Bir sınıfı asla başlatmazsam, ancak bir statik alana erişirsem, özel statik alanları başlatmak için kullanılan TÜM statik bloklar ve özel statik yöntemler o anda (sırayla) çağrılır mı?

Ya statik bir yöntem çağırırsam? Tüm statik blokları da çalıştırıyor mu? Yöntemden önce?


Yanıtlar:


156

Bir sınıfın statik başlatması normalde aşağıdaki olaylardan biri ilk kez gerçekleşmeden hemen önce gerçekleşir:

  • sınıfın bir örneği oluşturulur,
  • sınıfın statik bir yöntemi çağrılır,
  • sınıfın statik bir alanı atanır,
  • sabit olmayan bir statik alan kullanılır veya
  • üst düzey bir sınıf için, sınıf içinde sözcüksel olarak yuvalanmış bir assert ifadesi çalıştırılır 1 .

JLS 12.4.1'e bakınız .

Bir sınıfı Class.forName(fqn, true, classLoader)veya kısa biçim kullanarak başlatmaya zorlamak da mümkündür (daha önce başlatılmamışsa)Class.forName(fqn)


1 - Son madde işareti, Java 6 üzerinden Java 8 için JLS'de mevcuttu, ancak görünüşe göre şartnamede bir hataydı. Sonunda Java 9 JLS'de düzeltildi: kaynağa bakın .


9
Yine de ortak bir tuzak var. Temel öğeler ve Stringler ikame edilir ve referans gösterilmez. Bir class Other { public static final int VAL = 10; }sınıftan a'ya başvurursanız MyClass { private int = Other.VAL; }, sınıf Otheryüklenmeyecektir. Bunun yerine, derleyici derleme zamanında son alanı basitçe değiştirecektir.
Rafael Winterhalter

6
@RafaelWinterhalter - evet ... bu sabit statik alan durumudur.
Stephen C

2
@RafaelWinterhalter, bu tüm 'statik son' ilkel veya Stringdeğişkenler için geçerli değildir , yalnızca sabit bir ifadeyle başlatılanlar için geçerli değildir .
Lew Bloch

1
Evet ve staticbu yaygın durumdayken alanın olması bile gerekmez .
Rafael Winterhalter

1
Aynı programlama dilidir. Evet.
Stephen C

14

Statik alanlar , statik başlatıcıları ve statik alanlarının ilklendirmelerini içeren sınıf yüklemesinin (yükleme, bağlama ve başlatma) başlatma "aşaması" sırasında başlatılır . Statik başlatıcılar, sınıfta tanımlandığı gibi metinsel bir sırada yürütülür.

Örneği düşünün:

public class Test {

   static String sayHello()  {
      return a;
   }

   static String b = sayHello(); // a static method is called to assign value to b.
                                 // but its a has not been initialized yet.

   static String a = "hello";

   static String c = sayHello(); // assignes "hello" to variable c

    public static void main(String[] arg) throws Throwable {
         System.out.println(Test.b); // prints null
         System.out.println(Test.sayHello()); // prints "hello"
    }
}

Test.b , statik kapsamda çağrıldığında statik değişken başlatılmadığı nulliçin yazdırılır .sayHelloa


6
Açıkçası, başlatma, sınıf yüklemesinin bir "aşaması" değildir. Gerçekten de, bazı sınıflar olabilir yüklenen ancak uygulama aslında onlardan faydalanmak etmezse hiçbir zaman başlatıldı edilecek.
Stephen C

@Stephen C Haklısın, daha iyi bir terim olmadığı için kullandım, belki alıntı yaparım.
naikus

@StephenC, Sınıf yüklemesi gerçekleşirken, belleği statik değişkenlere (& yöntemlere) atadığı, ancak bu statik değişkenler kodda sağlanan değerlerle başlatılmadığı anlamına mı geliyor? çünkü burada, b-> sayHello () -> a, bellekte 'a' olduğu, ancak henüz ona değer atanmadığı zaman görünüyor.
Shabbir Essaji

Temelde evet.
Stephen C

1

Evet, tüm statik başlatıcılar, sınıfa ilk kez erişmeden önce çalıştırılır. Başka bir şekilde olsaydı, ben buna böcek derdim.


Bir sınıfa onu başlatmadan başvurmanın yolları vardır.
Lew Bloch
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.