Статичні поля на нульовій посилання на Java


119

staticчлени ( staticполя або staticметоди) в Java асоціюються з відповідним класом, а не з об'єктами цього класу. Наступний код намагається отримати доступ до статичного поля за nullпосиланням.

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

Хоча main.getNull()повертається null, він працює і відображається value = 10. Як працює цей код?



4
Для задоволення спробуйте Main main = null; main.getNull().value.
Марко Топольник

1
Це нагадує мені, new Thread[]{}[-1].sleep(10);де сон () є статичним методом. Це вдалося досягти успіху в деяких старих версіях Java.
hertzsprung

Відповіді:


93

Така поведінка визначена в специфікації мови Java :

нульова посилання може використовуватися для доступу до змінної класу (статичної), не викликаючи винятку.

Більш детально, статичне оцінювання поля , наприклад такі Primary.staticFieldроботи (акцент мій) - у вашому випадку Primary = main.getNull():

  • Первинний вираз оцінюється, а результат відкидається . [...]
  • Якщо поле є незаповненим кінцевим полем, то результатом є значення вказаної змінної класу в класі або інтерфейсі, що є типом вираження "Первинний". [...]

5
Якщо хтось має інформацію про те, чому такий вибір був зроблений, це було б цікаво.

6
@JonofAllTrades Я думаю, що це очевидно: розумно не кидати жодних винятків при виклику нульової посилання, оскільки це не має значення, оскільки метод є статичним.
Малькольм

13
@JonofAllTrades: справжнє питання полягає в тому, чому був зроблений вибір дозволу статичних членів називатися екземпляром ... Для мене, здається, це призводить лише до плутанини і менш читабельного коду.
Фаланве

2
@Falanwe: Погодився, і це конструкція, в якій у мене не було потреби, хоча я здебільшого працюю в .NET, де це не дозволено. Я думаю, ви можете зателефонувати на відповідний статичний метод підкласу, коли вам надається посилання на батьківський клас.

8
@Falanwe Це дозволено, але викликає попередження у Eclipse: "Статичне поле Main.value має бути доступне статичним способом". Принаймні ті з нас, прискіпливих до попереджень (як я), уникають такого коду.
Артем

19

Тому що, як ви сказали, статичні поля не асоціюються з екземпляром.

Можливість доступу до статичних полів із посилання на екземпляр (як ви робите) є лише синтаксичним цукром і не має додаткового значення.
Ваш код компілюється в

main.getNull(); 
Main.value

7
Я б назвав це синтаксичним цукром, більше схожим на синтаксичний пиловий пил;)
Stephen Swensen

3

Коли ви коли-небудь отримуєте доступ до статичної змінної або методу з об'єктами під час компіляції, він перетворюється на ім'я класу. наприклад:

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

Він надрукує значення статичної змінної, оскільки під час компіляції воно буде перетворене в

System.out.println(Main.value);

Доказ:

завантажте декомпілятор і декомпілюйте свій .class файл у .java-файл, і ви зможете побачити всі статичні методи або назву об'єкта з змінною назвами автоматично замінюється назвою класу.


3
  1. Доступ до staticчлена з назвою класу є законним, але його не було написано, що не можна отримати доступ до staticчлена за допомогою змінної посилання на об'єкт. Так це працює тут.

  2. До nullзмінній посилання на об'єкт дозволяється отримати доступ до staticзмінної класу, не викидаючи виняток ні під час компіляції, ні під час виконання.


2

Статична змінна та метод завжди належать до класу. Тож коли-небудь ми створюємо будь-який об’єкт, лише нестатична змінна і методи переходять в купу разом з об'єктом, але статична знаходиться в області методу з класом. Ось чому коли-небудь ми намагаємося отримати доступ до статичної змінної чи методу, який вона перетворила на точку змінної або ім'я методу класу.

Будь ласка, перегляньте посилання нижче для більш детальної інформації

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.