Java 7. Завершение обзора проекта “Монета”.


В двух постах до этого описал некоторые новшества из Project Coin – Java 7, а именно:

1) Дельфин, монета и бриллиантовый оператор.
– Improved type inference for generic instance creation (diamond)
– try-with-resources statement

2) Java 7. Строки в переключателе
– Strings in switch

Сейчас хотел описать три оставшихся нововведения:

– Целые числа в двоичном представлении и подчеркивание (Binary integral literals and underscores in numeric literals).
– Возможность ловить несколько разных исключений и более точная переброска (Multi-catch and more precise rethrow).
– Упрощенный вызов методов с переменным количеством аргументов (Simplified varargs method invocation).

1. Целые числа в двоичном представлении и подчеркивание.


Стало попроще работать с целыми числами.

Во-первых можно писать в двоичном виде:
int mask = 0b1000; // = 8
В итоге работать с битовыми масками стало намного удобней.

Пример из спецификации:

IntegerLiteral:
DecimalIntegerLiteral
HexIntegerLiteral
OctalIntegerLiteral
BinaryIntegerLiteral

BinaryIntegerLiteral:
BinaryNumeral IntegerTypeSuffixopt

BinaryNumeral:
0 b BinaryDigits
0 B BinaryDigits

BinaryDigits:
BinaryDigit
BinaryDigit BinaryDigitsAndUnderscoresopt BinaryDigit

BinaryDigitsAndUnderscores:
BinaryDigitOrUnderscore
BinaryDigitsAndUnderscores BinaryDigitOrUnderscore

BinaryDigitOrUnderscore:
BinaryDigit
_

BinaryDigit: one of
0 1

Другими словами формат такой: ноль (0), символ ‘b‘ или ‘B‘, затем последовательность чисел из 1 и 0, также между ними можно использовать знак подчеркивания ‘_’.
Что касается подчеркивания, то это тоже новшество Java 7. Скорее всего введено для улучшения человекочитаемости кода.

  int a = 555_445_577;
  int b = 0b1000_1111;

  // а вот так, нельзя:
  //   int с = _123; Не скопилируется! error: illegal underscore
  //   int d = 456_; Не скопилируется! error: illegal underscore

2. Возможность ловить несколько разных исключений и более точная переброска.

Интересная доработка с обработкой исключений:

   private static void multiCatch() throws IOException {
        FileInputStream fis = new FileInputStream("/tmp/1.txt")
        try {
            fis.read();
        } catch (FileNotFoundException | SecurityException e) {
            throw e;
        } finally {
            fis.close();
        }
    }

Внешне это похоже на то как будто мы, через оператор ‘|’ (или) указываем
классы исключения, для которых стоит выполнять указанный код-обработки .
То есть в данном примере для FileNotFoundException и SecurityException.
Это позволяет в некоторых местах убрать дублирующийся код, а это уже хоть малая, но приятная победа над злом.

Второе новшество more precise rethrow – более интересное.

Рассмотрим такой пример кода:

 private static void finalThrow() {
        try {
            throw new RuntimeException("test");
        } catch (final Exception e) {
            throw e;
        }
    }

Здесь в первую очередь сразу бросается в глаза final перед Exception!
Если бы мы попробовали скомпилировать такой код, в Java 6, то получили бы ошибку “… must be caught or declared to be thrown”!.

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

Интрига на этом не заканчивается. Самое интересное то, что люди начали возмущаться! Зачем указывать final?!
Это дополнительный (лишний) смысл к этому ключевому слову!
В итоге, поведение без final по-умолчанию (если это возможно) аналогично тому, как если бы мы указали final.

Например:

    private static void finalThrow() {
        try {
            throw new RuntimeException("test");
        } catch ( /* final */ Exception e) {
            // final можно не указывать.
            throw e;
        }
    }

   // НЕ СКОМПИЛИРУЕТСЯ!!!!!
    private static void finalThrow2() {
        try {
            throw new RuntimeException("test");
        } catch (Exception e) {
            // поломали. e - не final!!!!!!
            e = e;
            throw e;
        }
    }

3. Упрощенный вызов методов с переменным количеством аргументов.

Это улучшение больше похоже на хак.
Сделали новую аннотацию: SafeVarargs
Это аннотация глушит предупреждения, которые мог бы выкидывать компилятор при использовании женериков вместе с вараргами.

Пример использования этой аннотации можно посмотреть в документации: Arrays.asList().

Если честно, относительно этой фичи, мне лень (и не интересно) расписывать все детали и ее хитросплетения.
Кому любопытно, подробнее, можно почитать здесь: http://blogs.oracle.com/darcy/entry/project_coin_safe_varargs

Любое использование либо копирование материалов или подборки материалов сайта, элементов дизайна и оформления допускается лишь с разрешения правообладателя и только со ссылкой на источник: programador.ru

Телеграм канал: @prgrmdr
Почта для связи: vit [at] programmisty.com