Яка різниця між неініціалізованою змінною об'єкта і об'єктною змінною, ініціалізованою на null в Java


12

У мене є такі дві змінні об'єкта

Date a;
Date b=null;

Однозначно "a" і "b" не посилаються ні на які об'єкти.

Тепер, якщо я посилаюсь на наступне твердження

System.out.println(a.toString());

Буде помилка часу компіляції, тоді як якщо я посилаюсь на наступне твердження

System.out.println(b.toString());

Не буде помилки часу компіляції, але буде помилка виконання. У чому причина цього і яке значення буде фактично зберігатися у "b", щоб представляти нульове значення?


2
запитували і відповіли багато разів на SO: Чому локальні змінні не ініціалізуються на Java? , Неініціалізовані змінні та члени Java та багато питань, пов’язаних із цим
gnat

@gnat, чи вирішуються якісь інші питання щодо різниці між "неініціалізованими" та "нульовими"? Тільки тому, що відповідь схожа, не означає, що це повторне запитання.
DougM

@DougM впевнений, ти читав перше питання, про яке я згадав? "Чи була якась причина, чому дизайнери Java вважали, що локальним змінним не слід присвоювати значення за замовчуванням? Серйозно, якщо змінним екземпляра можна надати значення за замовчуванням, то чому ми не можемо зробити те ж саме для локальних змінних?" (FWIW технічно не може бути дублікатом, просто тому, що це на іншому сайті)
gnat

1
Це не вирішує різницю між "неініціалізованими" та "ініціалізованими як нульові", лише "чому змінні не ініціалізуються автоматично до нуля?" Та сама тема, трохи інше питання.
DougM

Відповіді:


3

Це тому, що стан локальних змінних контролюється в його межах

 // method/loop/if/try-catch etc...
 {
   Date d; // if it's not intialised in this scope then its not intialised  anywhere
 }

Що не стосується полів

class Foo{
 Date d; // it could be intialised anywhere, so its out of control and java will set to null for you
}

Тепер, навіщо його штрафу встановлювати змінну на нуль і використовувати її негайно? можливо, це історична помилка, яка іноді призводить до жахливих помилок

 {
  Date d = null;
  try{
  }catch{ // hide it here 
  }
  return d;
 } 

Тепер у чому смислова різниця?

Date d;

просто оголошує змінну , яка може містити посилання , що вказує на об'єкт типу Date, проте

Date d= null; 

робить точно так само, але посилання вказує на нуль цього разу, null - це як будь-яка посилання, він займає простір нативного вказівника, тобто 4 байти на 32-бітних машинах і 8 байт на 64-бітних машинах


це, здається, просто повторює пункт, зроблений і пояснений у попередній відповіді, опублікованій годину тому
гнат

@gnat Дякую за ваш коментар, але я не думаю, що це, ура!
Слейман Джаніді

Ви маєте на увазі, що null - це також об'єкт, який зберігається десь у пам'яті, і всі змінні об'єкта, присвоєні null, вказують на цей нульовий об'єкт.
Harish_N

@ Harish.N ні, я цього не говорив, я сказав, що це посилання, а не об'єкт
Слейман Джаніді

У наведеному вами прикладі "d" - це посилання .. це посилання на об'єкт типу Date ... аналогічно, якщо null є посиланням .. на який об'єкт посилається ..?
Harish_N

19

Для полів класу немає різниці. Вони nullза замовчуванням знаходяться для об'єктів, 0 для числових значень та falseбулевих значень .

Для змінних, оголошених у методах - Java вимагає їх ініціалізації. Якщо їх ініціалізація не викликає помилку часу компіляції під час доступу до них.

У чому причина? Поля класу можна змінювати будь-яким методом. У будь-якому порядку використовується метод. Усі неприватні поля можуть бути змінені іншими класами та / або класами, що поширюють цей клас. Отже, немає сенсу сповіщати про неініціалізовану змінну, оскільки вона може бути призначена у багатьох, багатьох місцях.

Змінні всередині методів, однак, є локальними і можуть бути змінені лише всередині самого методу. Отже, можна вказати на можливі помилки і раціонально. І компілятор намагається це зробити. Якщо воно знає, що поле не ініціалізовано, воно покаже помилку, оскільки це ніколи не те, що ви хочете. Якщо він не впевнений - він попередить, щоб ви могли переконатися.

public static class Test {
    Date a; // ok 
    Date b = null; // ok

    public void test() {
        Date c;
        Date d = null;

        System.out.println(a.toString());
        System.out.println(b.toString());
        System.out.println(c.toString()); // error
        System.out.println(d.toString()); // warning
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.