Ответ 1
Он ведет себя так, как должен, согласно Спецификация языка Java:
нулевая ссылка может использоваться для доступа к переменной класса (статической), не вызывая исключения.
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, как и следовало ожидать. Может кто-нибудь объяснить причину того же?
Он ведет себя так, как должен, согласно Спецификация языка Java:
нулевая ссылка может использоваться для доступа к переменной класса (статической), не вызывая исключения.
В основном вы вызываете статический метод, как если бы это был метод экземпляра. Это просто разрешено для вызова статического метода, так что, как если бы вы написали:
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);
Какой поток отправляет спать? Текущий, "конечно"...
Статические вызовы методов разрешаются во время компиляции. Компилятор видит, что getNull()
имеет возвращаемое значение типа A
, у которого есть статический метод getValue()
(и не метод экземпляра с тем же именем), поэтому в байт-коде фактическое возвращаемое значение getNull()
игнорируется и A.getValue()
.
Функция getNull возвращает объект A. getValue объявляется как статический, и ему просто нужно имя класса для функции, как в A.getValue(). Поскольку getNull возвращает (фактически) объект A... вы получите 1
System.out.println(m.getNull() GetValue().); эта строка кода такая же, как System.out.println(A.getValue());
так как метод getValue() статичен, и все статические вызовы инициируются во время компиляции в java. поэтому он не производит никаких ошибок, если вы сделаете getValue() в нестационарном режиме, это приведет к ошибке, поскольку потому, что он будет вызываться во время выполнения