Javanese Online

Ссылочные типы, null, @Nullable, @NotNull

Если передать значение примитивного типа в метод, оно будет скопировано:

public static void main(String[] args) {
    // объявляем переменную примитивного типа
    int voltage = 4100;

    // передаём
    add100mV(voltage);

    // 4100 — без изменений
    System.out.println(voltage);
}

private static void add100mV(int lowVoltage) {
    lowVoltage += 100;
    // Абсолютно бесполезное действие.
    // Переменная lowVoltage существует
    // только в пределах метода и уничтожается,
    // когда метод отработал.
}

Если передать объект в метод, будет передана ссылка на этот объект, т. е. в методе будет доступен тот же объект, не копия.

public static void main(String[] args) {
    int[] voltages = {4100};
    // массивы в Java — это объекты.
    add100mVToFirstElement(voltages); // передаём
    System.out.println(voltages[0]); // 4200
}
private static void add100mVToFirstElement(int[] lowVoltages) {
    lowVoltages[0] += 100;
    // Локальная переменная lowVoltages
    // указывает на массив,
    // мы прибавляем 100 мВ
    // к значению нулевого элемента
    // этого массива.
}

Это называется «передача по значению» и «передача по указателю (ссылке)» соответственно.

Кроме того, что можно указывать на объекты (например, int[] voltages = {4100}; или Phone myPhone = new Nexus5();), также можно указывать на пустое значение.

public static void main(String[] args) {
    int[] voltages = null;
    // пустой указатель
    add100mVToFirstElement(voltages); // передаём
}
private static void add100mVToFirstElement(int[] lowVoltages) {
    lowVoltages[0] += 100;
}

Результат:

Exception in thread "main" java.lang.NullPointerException
	at JavaneseNull.add100mVToFirstElement(JavaneseNull.java:11)
	at JavaneseNull.main(JavaneseNull.java:8)

Выполнение программы прервалось, т. к. произошла попытка чтения элемента из null. Ещё один пример безнадёжного кода:

MobilePhone mp = null;
mp.dial("*#06#");

null существует, чтобы показать отсутствие значения. Любая переменная объектного (ссылочного) типа, переданная извне, может оказаться null, поэтому в методах нужно проверять входные данные. Например:

private static void add100mVToFirstElement(int[] lowVoltages) {
    if (lowVoltages == null)
        throw new NullPointerException("lowVoltages == null, ожидался массив");
    if (lowVoltages.length < 1)
        throw new IllegalArgumentException("lowVoltages.length < 1, ожидался массив хотя бы с одним элементом");
    lowVoltages[0] += 100;
}

Если аргумент lowVoltages не пройдёт проверку, выполнение будет прервано с выбросом соответствующего исключения.

Если передать null:

NullPointerException

Если передать пустой массив:

IllegalArgumentException

Непустой массив:

Нормальное выполнение метода.

Успех!

Аннотации для борьбы с нулевыми указателями (null pointers)

Чтобы показать, что поле или параметр может быть null или метод может вернуть null, используется аннотация @Nullable.

@Nullable
private String toBeOrNotToBe;

@Nullable
public String toBeOrNotToBe() {
    return toBeOrNotToBe;
}

Чтобы, наоборот, показать, что поле или параметр не может быть null или метод не может вернуть null, используется аннотация @NotNull или @NonNull.

@NotNull
private final String name;

public User(@NotNull String name) {
    this.name = name;
}

Эти аннотации помогают среде разработки определить, где могут быть null, и предостеречь о возможных ошибках.

Комментарии
{"type":"lessonComments","id":"fa6e168a-67bd-446d-bc25-7b44559c3d19","comments":[]}

Сообщить об ошибке

Javanese.Online в GitHub

Чаты и каналы в Telegram

RSS-лента