Почему я могу бросить null в Java?


при запуске этого:

public class WhatTheShoot {

    public static void main(String args[]){
        try {
            throw null;
        } catch (Exception e){
            System.out.println(e instanceof NullPointerException);
            System.out.println(e instanceof FileNotFoundException);
        }
    }
}

ответ:

true  
false

который был довольно ошеломляющим для меня. Я бы подумал, что это чистая ошибка времени компиляции.

почему я могу бросить null в Java, и почему он поднимает его до NullPointerException?

(на самом деле, я не знаю, является ли это "upcast", учитывая, что я бросаю null)

кроме действительно очень глупого вопроса интервью (пожалуйста никто не спрашивает об этом в интервью) я не вижу никаких причин throw null. Может, ты и хочешь, чтобы тебя уволили, но это так... Я имею в виду, зачем еще кому-то throw null?

интересный фактIntelliJ IDEA 12 говорит мне, что моя линия,e instanceof NullPointerException, всегда будет ложным. А это совсем не так.

7 293

7 ответов:

похоже, что это не так null трактуется как NullPointerException, но это акт попытки throw null бросает a NullPointerException.

другими словами, throw проверяет, что его аргумент nonnull, и если он равен null, он выдает NullPointerException.

JLS 14.18 указывает поведение:

если вычисление выражения завершается нормально, производя нулевое значение, то экземпляр V ' класса NullPointerException создается и выбрасывается вместо null. Затем оператор throw завершается резко, причиной чего является бросок со значением V'.

Почему он поднимает его до NullPointerException?

по состоянию на JLS 14.18:

оператор throw сначала вычисляет выражение. Если оценка выражения завершается внезапно по какой-то причине, то бросок завершается резко по этой причине. Если вычисление выражения завершается нормально, производя ненулевое значение V, то оператор throw завершается резко, причиной является бросок со значением V. если вычисление выражения завершается нормально, производя нулевое значение, то создается экземпляр V’ класса NullPointerException и выбрасывается вместо null. оператор throw затем завершается резко, причиной является бросок со значением V'.

Почему я могу бросить null в java ?

вы можете бросать объекты типа Throwable и с null является допустимой ссылкой для Throwable , компилятор позволяет это сделать.

Это что Нил Гафтер говорит

хотя null присваивается каждому ссылочному типу, тип null сам по себе не является ссылочным типом. Наше намерение состояло в том, чтобы требование о том, чтобы выражение в операторе throw было ссылочным типом, должно было быть удалено из третьего издания JLS, но это изменение никогда не вносило его в опубликованную версию. Таким образом, это ошибка компилятора javac, которую я представил в SE 5.

Он ведет себя в соответствии с JLS:

Если вычисление выражения завершается нормально, производя нулевое значение, то создается экземпляр V' класса NullPointerException и выбрасывается вместо null.

думая об этом таким образом, делает его немного более очевидным, почему это работает:

try {
    Exception foo = null;
    if(false) {
        foo = new FileNotFoundException();
    } // Oops, forgot to set foo for the true case..
    throw foo;
} catch (Exception e){
    System.out.println(e instanceof NullPointerException);
    System.out.println(e instanceof FileNotFoundException);
}

Не знаю точно, но я предполагаю, что "throw null"; does не работа, и попытка его вызывает программу, чтобы бросить исключение, и это исключение случается быть (барабанная дробь) NullPointerException...

null может быть приведено к чему угодно*, включая исключение. Так же, как вы можете вернуть null, если ваша подпись метода указывает, что вы должны вернуть исключение (или действительно строку или класс Person), вы можете его бросить.

*за исключением примитивных типов.

bharal...It выглядит ошибка компилятора javac. Я думаю, что это было введено в SE 5. Null может быть присвоен любому ссылочному типу. Однако "тип null" сам по себе не является ссылочным типом. Программа компилирует его, потому что null может просто привести к исключению. И более того, throw ищет ссылку на объект после объявления, и поскольку null может работать как ссылка на объект, он отображает результат.

документ JLS о броске как:

" сначала оператор броска вычисляет выражение. Если оценка выражение завершается резко по какой-то причине, затем бросок завершается резко по этой причине. Если оценка выражения завершается нормально, создавая ненулевое значение V, затем бросок оператор завершается резко по той причине, бросок с значение В. Если вычисление выражения завершается нормально, то создается значение null значение, затем создается экземпляр V ' класса NullPointerException и бросил вместо null. Этот затем завершается оператор throw внезапно, причиной является бросок со значением V'."