Щоб зрозуміти, навіщо потрібен null в Java, наведемо аналогію з числами: число 0 символізує відсутність будь-чого, а null означає те саме для посилальних типів даних. Якщо полю посилального типу (String, Object, StringBuilder) не присвоїти жодного знання за аналогією з примітивними типами, воно отримає значення за замовчуванням, і цим значенням буде null:

Код Виведення на екран

public class Solution {

    public static int i;
    public static String s;

    public static void main(String[] args) {
        System.out.println(i);
        System.out.println(s);
    }
}
                    
0
null

А якщо оголосити масив у такий спосіб:


String[] strings = new String[12];

створиться масив, що містить 12 елементів, і всі вони дорівнюватимуть null:

Код Виведення на екран

public class Solution {
    public static void main(String[] args) {
        String[] strings = new String[12];

        for (int i = 0; i < strings.length; i++) {
            System.out.println(i + "-й елемент: " + strings[i]);
        }
    }
}
                    
0-й елемент: null
1-й елемент: null
2-й елемент: null
3-й елемент: null
4-й елемент: null
5-й елемент: null
6-й елемент: null
7-й елемент: null
8-й елемент: null
9-й елемент: null
10-й елемент: null
11-й елемент: null

Як бачиш, під час конкатенації з рядком null перетворюється на рядок null. Хоча, якщо викликати в нього метод toString():


String[] strings = null;
System.out.println(strings.toString());

отримаєш NullPointerException (виключення ми пізніше розберемо детально). Те саме станеться, якщо спробувати викликати у null будь-який інший метод (виняток — статичні методи, з якими ти незабаром ознайомишся):


public static void main(String[] args) {
    StringBuilder sb = null;
    sb.append("test"); // скомпілюється, але при виконанні буде помилка
}

null, окрім іншого, — зарезервоване ключове слово (як public або static), отже не вдасться створити змінну, метод або клас з ім’ям null. Це ключове слово, як і інші, реєстрозалежне (ти міг звернути увагу, що ми скрізь пишемо null із маленької літери), тому:


String firstName = Null; // буде помилка компіляції

String secondName = NULL; // буде помилка компіляції

String fullName = null; // скомпілюється

Розглянемо, що ще можна і не можна робити з null:

  • Будь-якому посиланню можна присвоїти null:

    
    StringBuilder sb = null;
                
  • null можна привести до будь-якого посилального типу:

    
    String s = (String) null; // скомпілюється, хоча сенсу не додасть :)
                
  • null не можна присвоїти примітивній змінній:

    
    int i = null; // не скомпілюється
                
  • null можна порівнювати за допомогою == i !=

  • null == null повертає true

У попередніх лекціях ми розповідали, що в Java все є об’єктом, і кожен об’єкт має тип.

Що ми можемо щодо цього сказати про null? null – це літерал якогось типу, і у цього типу немає імені. А оскільки у цього типу немає імені, неможливо оголосити змінну цього типу або зробити приведення до нього. Отже, null – єдиний представник цього безіменного типу. На практиці ж ми можемо ігнорувати цей тип і представляти null як спеціальний літерал, який можна присвоїти змінній будь-якого посилального типу.

Що важливо запам’ятати:

  • null – це значення за замовчуванням для посилальних типів даних;
  • null – це «відсутність значення»;
  • якщо об’єкт, значення якого дорівнює null, викликати будь-який метод – компіляція такого коду пройде, а під час виконання матимемо виняток NullPointerException.