Почему этот код НЕ возвращает исключение NullPointerException?

public class Main
{
   public static void main(String []ar)
   {
      A m = new A();
      System.out.println(m.getNull().getValue());
   }
}

class A
{
   A getNull()
   {
      return null;
   }

   static int getValue()
   {
      return 1;
   }
}

Я столкнулся с этим вопросом в книге SCJP. Код выводит 1 вместо NPE, как и следовало ожидать. Может кто-нибудь объяснить причину того же?

Ответы

Ответ 1

Он ведет себя так, как должен, согласно Спецификация языка Java:

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

Ответ 2

В основном вы вызываете статический метод, как если бы это был метод экземпляра. Это просто разрешено для вызова статического метода, так что, как если бы вы написали:

A m = new A();
m.getNull();
System.out.println(A.getValue());

IMO тот факт, что ваш код является законным, является ошибкой дизайна на Java. Это позволяет писать очень вводящий в заблуждение код, Thread.sleep в качестве примера я всегда использую:

Thread thread = new Thread(someRunnable);
thread.start();
thread.sleep(1000);

Какой поток отправляет спать? Текущий, "конечно"...

Ответ 3

Статические вызовы методов разрешаются во время компиляции. Компилятор видит, что getNull() имеет возвращаемое значение типа A, у которого есть статический метод getValue() (и не метод экземпляра с тем же именем), поэтому в байт-коде фактическое возвращаемое значение getNull() игнорируется и A.getValue().

Ответ 4

Функция getNull возвращает объект A. getValue объявляется как статический, и ему просто нужно имя класса для функции, как в A.getValue(). Поскольку getNull возвращает (фактически) объект A... вы получите 1

Ответ 5

System.out.println(m.getNull() GetValue().); эта строка кода такая же, как System.out.println(A.getValue());

так как метод getValue() статичен, и все статические вызовы инициируются во время компиляции в java. поэтому он не производит никаких ошибок, если вы сделаете getValue() в нестационарном режиме, это приведет к ошибке, поскольку потому, что он будет вызываться во время выполнения