Java'da boş bir referanstaki statik alanlar


119

staticJava'daki üyeler ( staticalanlar veya staticyöntemler), bu sınıfın nesneleri yerine kendi sınıflarıyla ilişkilendirilir. Aşağıdaki kod, bir nullreferanstaki statik bir alana erişmeye çalışır .

public class Main
{
    private static final int value = 10;

    public Main getNull()
    {
        return null;
    }

    public static void main(String[] args)
    {
        Main main=new Main();
        System.out.println("value = "+main.getNull().value);
    }
}

Her ne kadar main.getNull()getiri null, nasıl çalıştığını ve görüntüler value = 10. Bu kod nasıl çalışır?



4
Eğlenmek için deneyin Main main = null; main.getNull().value.
Marko Topolnik

1
Bu bana new Thread[]{}[-1].sleep(10);sleep () 'in statik bir yöntem olduğunu hatırlatıyor . Bu, bazı eski Java sürümlerinde başarılı oluyordu.
hertzsprung

Yanıtlar:


93

Bu davranış Java Dil Spesifikasyonunda belirtilmiştir :

bir istisnaya neden olmadan bir sınıf (statik) değişkenine erişmek için boş bir başvuru kullanılabilir.

Daha ayrıntılı olarak, aşağıdaki gibi çalışır (vurgu benim) gibi statik bir alan değerlendirmesiPrimary.staticField - sizin durumunuzda Primary = main.getNull():

  • Birincil ifade değerlendirilir ve sonuç atılır . [...]
  • Alan boş olmayan bir son alansa, sonuç, birincil ifadenin türü olan sınıf veya arabirimde belirtilen sınıf değişkeninin değeridir. [...]

5
Bu seçimin neden yapıldığına dair bilgisi olan biri varsa , bu ilginç olurdu.

6
@JonofAllTrades Bunun açık olduğunu düşünüyorum: boş bir referansı çağırırken herhangi bir istisna atmamak mantıklı çünkü yöntem statik olduğu için önemli değil.
Malcolm

13
@JonofAllTrades: Asıl soru, statik üyelerin örnek olarak çağrılmasına izin verme seçiminin neden yapıldığı ... Bana göre bu sadece kafa karışıklığına ve daha az okunabilir koda yol açıyor.
Falanwe

2
@Falanwe: Kabul edildi ve ihtiyacım olmayan bir yapı, ancak izin verilmeyen yerlerde çoğunlukla .NET'te çalışıyorum. Bir ana sınıfa referans verildiğinde bir alt sınıfın uygun statik yöntemini çağırmak isteyebileceğinizi tahmin ediyorum.

8
@Falanwe Buna izin verilir, ancak Eclipse'de bir uyarı verir: "Main.value statik alanına statik bir şekilde erişilmelidir". En azından uyarılar konusunda seçici olanlar (benim gibi) bu tür kodlardan kaçınır.
Artyom

19

Çünkü sizin de söylediğiniz gibi statik alanlar bir örnekle ilişkilendirilmez.

Bir örnek referansından statik alanlara erişme yeteneği (yaptığınız gibi) yalnızca sözdizimsel bir şekerdir ve ek bir anlamı yoktur.
Kodunuz derlenir

main.getNull(); 
Main.value

7
Ben buna sözdizimsel şeker diyebilirim, daha çok sözdizimsel testere tozu gibi;)
Stephen Swensen

3

Derleme zamanında nesnelerle statik bir değişkene veya yönteme eriştiğinizde, sınıf adına dönüştürülür. Örneğin:

Main main = null;
System.out.println(main.value);

Statik değişken değerinin değerini yazdıracaktır çünkü derleme zamanında dönüştürülecektir.

System.out.println(Main.value);

Kanıt:

decompiler'ı indirin ve .class dosyanızı .java dosyasına yeniden derleyin ve tüm statik yöntemlerin veya değişkenle ilgili nesne adının otomatik olarak sınıf adıyla değiştirildiğini görebilirsiniz.


3
  1. staticSınıf adı ile bir üyeye erişim yasaldır, ancak staticnesne referans değişkenini kullanarak üyeye erişilemeyeceği yazılmıştır . Yani burada çalışıyor.

  2. Bir nullnesne başvurusu değişkeninin, staticderleme veya çalışma zamanında bir istisna oluşturmadan bir sınıf değişkenine erişmesine izin verilir .


2

Statik değişken ve yöntem her zaman sınıfa aittir. Bu nedenle, herhangi bir nesneyi yarattığımızda, yalnızca statik olmayan değişken ve yöntemler nesne ile birlikte yığına gider, ancak statik, sınıfla birlikte yöntem alanında bulunur. Bu nedenle, statik bir değişkene veya yönteme erişmeye çalıştığımızda, sınıf adı nokta değişkenine veya yöntem adına dönüştürülür.

Daha fazla ayrıntı için lütfen aşağıdaki bağlantıya bakın.

http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html

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.