Подтвердить что ты не робот

В чем разница между "(Object) null" и "null" в Java?

Взгляните на следующий пример:

class nul
{
  public static void main (String[] args)
  {
    System.out.println (String.valueOf((Object)null));
    System.out.println (String.valueOf(null));
  }
}

Первая println записывает null, а вторая бросает a NullPointerException.

Почему только вторая строка стоит исключения? И в чем разница между двумя null s? Есть ли в Java реальный null и поддельный null?

4b9b3361

Ответ 1

Первый вызов вызовет метод String.valueOf(Object), поскольку вы явно указали null на Object ссылку. И наоборот, второй вызовет перегруженный метод String.valueOf(char[]), поскольку char[] более определен, чем Object для аргумента null,

Существуют и другие перегруженные версии этого метода, которые принимают примитивные параметры, но они не являются допустимыми для аргумента null.

От JLS & sect; 15.12.2:

Может быть более одного такого метода, и в этом случае выбирается конкретный. Дескриптор (подпись плюс тип возврата) наиболее конкретным методом является метод, используемый во время выполнения для выполнения метода отправка.

Метод применим, если он применяется либо подтипированием (§15.12.2.2), применимые путем преобразования обращения метода (§15.12.2.3), или это применимый метод переменной arity (§15.12.2.4).

[...]

Если было установлено несколько применимых методов во время одного из три этапа тестирования применимости, то наиболее конкретным является выбрано, как указано в разделе § 15.12.2.5.

Теперь проверьте исходный код обоих методов:

// This won't throw NPE for `obj == null`
public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

// This will throw `NPE` for `data == null`
public static String valueOf(char data[]) {
    return new String(data);
}

Ответ 2

В Java много перегруженных методов String.valueOf. Кроме того, в Java null есть все и все типы, так что все, что не является примитивным, может быть null.

Итак, когда вы вызываете (String.valueOf((Object)null), вы вызываете метод valueOf, который принимает значение Object, поскольку явно используется null to Object.

Во втором примере вы явно не применяете null к любому конкретному типу, поэтому на самом деле вы вызываете метод valueOf с помощью char[], который выдает NPE.

Из JLS §15.12.2

Второй шаг выполняет поиск типа, определенного на предыдущем шаге, для. Этот шаг использует имя метода и типы выражения аргументов для определения доступных методов и применимыми, то есть объявлениями, которые могут быть правильно использованы данные аргументы.

Может быть более одного такого метода, и в этом случае выбирается конкретный. Дескриптор (подпись плюс тип возврата) наиболее конкретным методом является метод, используемый во время выполнения для выполнения метода отправка.

В этом случае char[] более специфичен, чем Object, поэтому он вызывается, когда не создается явный листинг null.

Ответ 3

Хотя я уже принял ответ, я хотел бы добавить точный ответ на вопрос, потому что два ответа сосредоточены на объяснении ловушки, в которую я вошел.

Разница между (Object)null и null заключается в том, что тип первого принудительно привязан к Object, но тип второго не является, как можно было бы думать, принудительным для Object. Вместо этого он может также быть массивом вместо объекта.

Таким образом, вывод следующий: передать (Object)null вместо null в качестве аргумента для метода, чтобы точно получить метод, работающий над объектами, а не любой другой метод, работающий с массивами.