Java 7-Precise rethrow с последним исключением

в предыдущих версиях java перестроение исключения рассматривалось как выбрасывание типа параметра catch.

например:

public static void test() throws Exception{
    DateFormat df = new SimpleDateFormat("yyyyMMdd");
    try {
        df.parse("x20110731");
        new FileReader("file.txt").read();
    } catch (Exception e) {
        System.out.println("Caught exception: " + e.getMessage());
        throw e;
    }
}

в Java 7 Вы можете быть более точными об исключении, если вы объявите исключение final:

//(doesn't compile in Java<7)
public static void test2() throws ParseException, IOException{
    DateFormat df = new SimpleDateFormat("yyyyMMdd");
    try {
        df.parse("x20110731");
        new FileReader("file.txt").read();
    } catch (final Exception e) {
        System.out.println("Caught exception: " + e.getMessage());
        throw e;
    }
}

у меня вопрос: документы говорят, что мне нужно объявить исключение final. Но если я этого не сделаю, код выше все еще компилируется и работает. Я что-то упускаю?

ссылки:

Project Coin: multi-catch и окончательный rethrow
добавить более гибкую проверку повторно исключения

3 ответов


Я верить Я видел твит от Джоша Блоха, говорящий, что" окончательное " ограничение было снято поздно. Я посмотрю, смогу ли я найти сообщение об этом, но я подозреваю, что любая "ранняя" документация, которую Вы читаете, теперь неточна.

EDIT: я не могу найти точный пост" он изменился", но Java 7 состояния документации показывает пример с него не быть окончательной. Он говорит об исключительных переменных имплицитно final, когда блок catch объявляет более одного типа, но это немного отдельно.

EDIT: теперь я нашел источник моей путаницы, но это сообщение внутреннего списка рассылки: (во всяком случае, его не нужно объявлять окончательным, но я считаю, что компилятор рассматривает его как имплицитно final-как и в сценарии с несколькими уловами.


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

поэтому, чтобы ваш пример не компилировался, вам нужно каким-то образом изменить e, например:

public static void test2() throws ParseException, IOException {
    DateFormat df = new SimpleDateFormat("yyyyMMdd");
    try {
        df.parse("x20110731");
        new FileReader("file.txt").read();
    } catch (Exception e) {
        if (e instanceof ParseException) {
            e = new ParseException("Better message", 0);
        } else {
            e = new IOException("Better message");
        }
        System.out.println("Caught exception: " + e.getMessage());
        throw e; //does not compile any more
    }
}

без финала он по-прежнему действителен java. Вы просто теряете преимущество "точности".