Статьи

10 возможностей JDK 7 для повторного посещения, прежде чем приветствовать Java 8

Уже почти месяц выпускается Java 8, и я уверен, что все вы изучаете новые функции JDK 8. Но прежде чем полностью погрузиться в Java 8, пришло время вернуться к некоторым интересным функциям, представленным в Java 7. Если вы помните, что в Java 6 не было ничего особенного, все было связано с изменениями и производительностью JVM, но JDK 7 действительно представил некоторые интересные функции, которые улучшили повседневную задачу разработчика. Почему я пишу этот пост сейчас? Почему я говорю о Java 1. 7, когда все говорят о Java 8? Ну, я думаю, не все разработчики Java знакомы с изменениями, внесенными в JDK 7, и в какое время лучше вернуться к более ранней версии, чем до появления новой версии. Я не вижу автоматического управления ресурсами, используемого разработчиком в повседневной жизни, даже после того, как у IDE для этого есть помощь с контентом. Хотя я вижу программистов, использующих String в Switch и оператор Diamond для вывода типов, опять же, очень мало известно о каркасе fork fork , перехватывающем множественные исключения в одном блоке catch или использующем подчеркивание на числовых литералах. Поэтому я воспользовался этой возможностью, чтобы написать краткий пост, чтобы пересмотреть эти удобные изменения и перенести их в нашу повседневную жизнь. Есть несколько хороших изменений в NIO и новом File API, а также множество других на уровне API, которые также стоит посмотреть. Я уверен, что в сочетании с лямбда-выражением Java 8 эти функции приведут к гораздо лучшему и более чистому коду.

  1. Тип вывода
  2. В JDK 1.7 был введен новый оператор <<, известный как оператор ромба, чтобы сделать вывод типов доступным и для конструкторов. До Java 7 вывод типов был доступен только для методов, и Джошуа Блох правильно предсказал в Effective Java 2nd Edition, теперь он доступен и для конструктора . До JDK 7 вы вводили больше, чтобы указать типы как в левой, так и в правой части выражения создания объекта, но теперь это нужно только в левой части, как показано в примере ниже.

    До JDK 7

    1
    2
    Map<String, List<String>> employeeRecords =  new HashMap<String, List<String>>();
    List<Integer> primes = new ArrayList<Integer>();

    В JDK 7

    1
    2
    Map<String, List<String>> employeeRecords =  new HashMap<>();
    List<Integer> primes = new ArrayList<>();

    Таким образом, вы должны меньше печатать в Java 7, работая с коллекциями, где мы широко используем Generics . Смотрите здесь для более подробной информации о бриллиантовом операторе в Java.

  3. Строка в переключателе
  4. До JDK 7 только целочисленные типы можно использовать в качестве селектора для оператора switch-case. В JDK 7 вы можете использовать объект String в качестве селектора. Например,

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    String state = "NEW";
     
    switch (day) {
       case "NEW": System.out.println("Order is in NEW state"); break;
       case "CANCELED": System.out.println("Order is Cancelled"); break;
       case "REPLACE": System.out.println("Order is replaced successfully"); break;
       case "FILLED": System.out.println("Order is filled"); break;
       default: System.out.println("Invalid");
     
    }

    Для сравнения используется метод equals () и hashcode () из java.lang.String, который учитывает регистр. Преимущество использования String в switch заключается в том, что компилятор Java может генерировать более эффективный код, чем использование вложенного оператора if-then-else. Смотрите здесь для более подробной информации о том, как использовать String on Switch case .

  5. Автоматическое управление ресурсами
  6. Перед JDK 7 нам нужно использовать блок finally , чтобы гарантировать, что ресурс закрыт независимо от того, завершается ли оператор try нормально или внезапно, например, при чтении файлов и потоков, нам необходимо закрыть их в блок finally, что приводит к много котельной плиты и грязный код, как показано ниже:

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public static void main(String args[]) {
            FileInputStream fin = null;
            BufferedReader br = null;
            try {
                fin = new FileInputStream("info.xml");
                br = new BufferedReader(new InputStreamReader(fin));
                if (br.ready()) {
                    String line1 = br.readLine();
                    System.out.println(line1);
                }
            } catch (FileNotFoundException ex) {
                System.out.println("Info.xml is not found");
            } catch (IOException ex) {
                System.out.println("Can't read the file");
            } finally {
                try {
                    if (fin != null) fin.close();
                    if (br != null) br.close();
                } catch (IOException ie) {
                    System.out.println("Failed to close files");
                }
            }
        }

    Посмотрите на этот код, сколько строк кодов котлов?

    Теперь в Java 7 вы можете использовать функцию try-with-resource для автоматического закрытия ресурсов, которая реализует интерфейс AutoClosable и Closeable, например, «Потоки», «Файлы», дескрипторы сокетов, соединения с базой данных и т. Д. JDK 7 представляет оператор «try-with-resources», который обеспечивает что каждый из ресурсов в try (resources) закрывается в конце оператора, вызывая метод close () из AutoClosable. Теперь тот же пример в Java 7 будет выглядеть ниже, гораздо более лаконичный и понятный код:

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    public static void main(String args[]) {
           try (FileInputStream fin = new FileInputStream("info.xml");
      BufferedReader br = new BufferedReader(new InputStreamReader(fin));) {
      if (br.ready()) {
       String line1 = br.readLine();
       System.out.println(line1);
      }
     } catch (FileNotFoundException ex) {
      System.out.println("Info.xml is not found");
     } catch (IOException ex) {
      System.out.println("Can't read the file");
     }
    }

    Так как Java заботится о закрытии открытых ресурсов, включая файлы и потоки, возможно, утечка файловых дескрипторов не утечет, и, возможно, нет конца файловой дескриптору. Даже JDBC 4.1 также модернизируется как AutoClosable.

  7. Fork Join Framework
  8. Платформа fork / join является реализацией интерфейса ExecutorService, который позволяет вам использовать преимущества нескольких процессоров, доступных на современных серверах. Он предназначен для работы, которая может быть рекурсивно разбита на более мелкие части. Цель состоит в том, чтобы использовать всю доступную вычислительную мощность для повышения производительности вашего приложения. Как и в любой реализации ExecutorService, инфраструктура fork / join распределяет задачи среди рабочих потоков в пуле потоков. Структура соединения форка отличается тем, что использует алгоритм кражи работы, который сильно отличается от алгоритма потребителя производителя . Рабочие потоки, которым не хватает дел, могут украсть задачи из других потоков, которые все еще заняты. Центром структуры fork / join является класс ForkJoinPool, расширение класса AbstractExecutorService. ForkJoinPool реализует основной алгоритм кражи работ и может выполнять процессы ForkJoinTask. Вы можете заключить код в подкласс ForkJoinTask, такой как RecursiveTask (который может вернуть результат) или RecursiveAction. Смотрите здесь для получения дополнительной информации о фреймворке fork join в Java.

  9. Подчеркивание в числовых литералах
  10. В JDK 7 вы можете вставить подчеркивание (я) между цифрами в числовых литералах (целочисленные и литералы с плавающей точкой), чтобы улучшить читаемость. Это особенно ценно для людей, которые используют большое количество в исходных файлах, может быть полезно в финансовой и вычислительной областях. Например,

    1
    2
    3
    4
    5
    int billion = 1_000_000_000;  // 10^9
    long creditCardNumber =  1234_4567_8901_2345L; //16 digit number
    long ssn = 777_99_8888L;
    double pi = 3.1415_9265;
    float  pif = 3.14_15_92_65f;

    Вы можете поставить подчеркивание в удобных точках, чтобы сделать его более читабельным, например, для больших сумм целесообразно ставить подчеркивание между тремя цифрами, а для номеров кредитных карт длиной 16 цифр ставить подчеркивание после 4-й цифры, так как они печатаются в карточках. Кстати, помните, что вы не можете поставить подчеркивание сразу после десятичного числа или в начале, или в конце числа. Например, следующие числовые литералы недопустимы из-за неправильного размещения подчеркивания:

    1
    2
    3
    double pi = 3._1415_9265; // underscore just after decimal point
    long creditcardNum = 1234_4567_8901_2345_L; //underscore at the end of number
    long ssn = _777_99_8888L; //undersocre at the beginning

    См. Мой пост о том, как использовать подчеркивание на числовых литералах для получения дополнительной информации и варианта использования.

  11. Отлов нескольких типов исключений в одном блоке уловов
  12. Java 7 новая функция поваренная книга В JDK 7 один блок catch может обрабатывать несколько типов исключений.

    Например, до JDK 7 вам нужно два блока catch для перехвата двух типов исключений, хотя оба выполняют одинаковую задачу:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    try {
     
       ......
     
    } catch(ClassNotFoundException ex) {
       ex.printStackTrace();
    } catch(SQLException ex) {
       ex.printStackTrace();
    }

    В JDK 7 вы можете использовать один единственный блок catch с типами исключений, разделенными ‘|’.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    try {
     
       ......
     
    } catch(ClassNotFoundException|SQLException ex) {
     
       ex.printStackTrace();
     
    }

    Кстати, просто помните, что альтернативы в операторе multi-catch не могут быть связаны подклассами. Например, оператор multi-catch, как показано ниже, выдаст ошибку времени компиляции:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    try {
     
       ......
     
    } catch (FileNotFoundException | IOException ex) {
     
       ex.printStackTrace();
     
    }

    Альтернативы в операторе multi-catch не могут быть связаны подклассами, это вызовет ошибку во время компиляции: java.io.FileNotFoundException является подклассом альтернативного java.io.IOException в Test.main (Test.java:18)

    смотрите здесь, чтобы узнать больше об улучшенной обработке исключений в Java SE 7 .

  13. Двоичные литералы с префиксом «0b»
  14. В JDK 7 вы можете выражать литеральные значения в двоичном виде с префиксом «0b» (или «0B») для целочисленных типов (byte, short, int и long), аналогично языку C / C ++. До JDK 7 вы можете использовать только восьмеричные значения (с префиксом «0») или шестнадцатеричные значения (с префиксом «0x» или «0X»).

    1
    int mask = 0b01010000101;

    или даже лучше

    1
    int binary = 0B0101_0000_1010_0010_1101_0000_1010_0010;

  15. Java NIO 2.0
  16. Java SE 7 представила пакет java.nio.file и связанный с ним пакет java.nio.file.attribute, обеспечивающий всестороннюю поддержку файлового ввода-вывода и доступа к файловой системе по умолчанию. Он также представил класс Path, который позволяет вам представлять любой путь в операционной системе. Новый API файловой системы дополняет старый и предоставляет несколько полезных методов проверки, удаления, копирования и перемещения файлов. например, теперь вы можете проверить, скрыт ли файл в Java . Вы также можете создавать символические и жесткие ссылки из кода Java. Новый файловый API JDK 7 также способен искать файлы с использованием подстановочных знаков. Вы также получаете поддержку для просмотра каталога изменений. Я бы порекомендовал проверить документацию по Java нового пакета файлов, чтобы узнать больше об этой интересной полезной функции

  17. G1 Сборщик мусора
  18. JDK 7 представил новый сборщик мусора, известный как сборщик мусора G1, который вначале является короткой формой мусора. Сборщик мусора G1 выполняет очистку там, где больше всего мусора. Чтобы достичь этого, он разбил кучную память Java на несколько областей, а не на 3 области в предыдущей версии Java 7 (новое, старое и постоянное пространство). Говорят, что G1 вполне предсказуем и обеспечивает большую отдачу для приложений, интенсивно использующих память.

  19. Более точное повторное исключение
  20. Компилятор Java SE 7 выполняет более точный анализ переброшенных исключений, чем более ранние выпуски Java SE. Это позволяет вам указывать более конкретные типы исключений в предложении throws объявления метода . до JDK 7 повторное выбрасывание исключения обрабатывалось как выбрасывание типа параметра catch. Например, если ваш блок try может генерировать ParseException, а также IOException. Чтобы перехватить все исключения и перебросить их, вам нужно будет перехватить Exception и объявить свой метод как генерирующий Exception. Это своего рода непонятный неточный бросок, потому что вы генерируете тип общего исключения (вместо конкретных), и операторы, вызывающие ваш метод, должны перехватить это общее исключение. Это станет более понятным, увидев следующий пример обработки исключений в коде до Java 1.7

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public void obscure() throws Exception{
        try {
            new FileInputStream("abc.txt").read();
            new SimpleDateFormat("ddMMyyyy").parse("12-03-2014");       
        } catch (Exception ex) {
            System.out.println("Caught exception: " + ex.getMessage());
            throw ex;
        }
    }

    Начиная с JDK 7, вы можете быть более точным при объявлении типа Exception в выражении throws любого метода. Эта точность в определении того, какое Исключение выдается из того факта, что, если вы повторно выбрасываете исключение из блока catch, вы фактически генерируете тип исключения, который:

      1. ваш блок попытки может бросить,
      2. не обрабатывается ни одним предыдущим блоком catch, и
      3. является подтипом одного из исключений, объявленных как параметр catch

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public void precise() throws ParseException, IOException {
        try {
            new FileInputStream("abc.txt").read();
            new SimpleDateFormat("ddMMyyyy").parse("12-03-2014");       
        } catch (Exception ex) {
            System.out.println("Caught exception: " + ex.getMessage());
            throw ex;
        }
    }

    Компилятор Java SE 7 позволяет вам указать типы исключений ParseException и IOException в предложении throws в объявлении метода preciese (), потому что вы можете повторно вызвать исключение, которое является супертипом любого из типов, объявленных в throw, мы бросаем java.lang.Exception, который является суперклассом всех проверенных исключений . Также в некоторых местах вы увидите заключительное ключевое слово с параметром catch, но это больше не является обязательным.

Это все о том, что вы можете пересмотреть в JDK 7. Все эти новые функции Java 7 очень полезны для вашей цели по достижению чистого кода и производительности разработчиков. С появлением лямбда-выражения в Java 8 эта цель по очистке кода в Java достигла еще одной вехи. Дайте мне знать, если вы считаете, что я упустил какую-либо полезную функцию Java 1.7, которая, по вашему мнению, должна быть здесь.

PS Если вы любите книги, то вам может понравиться Java 7 Новые функции Cookbook из Packet Publication.