Я начал писать пост в блоге о том, что нового появилось в следующем выпуске Java8 , и подумал, что начну с того, что быстро оглянемся на то, что Java7 принес нам.
Java7 был выпущен еще в июле 2011 года и был описан как «скорее эволюционный, чем революционный».
«Есть некоторые значительные улучшения, но нет действительно потрясающих или новаторских функций». — Oracle главный архитектор Java Марк Рейнхольд
Например, в нем не было много раскрученных лямбда-выражений. Тем не менее, он внес много других полезных дополнений в язык Java. Вы можете увидеть больше на http://docs.oracle.com/javase/7/docs/ или прочитать мое резюме.
Основные моменты Java7 включены:
- Проектная монета
- Строки в выключателе
- оператор проб с ресурсами
- Мульти-улов и более точное отбрасывание
- Алмазный оператор
- Двоичные целочисленные литералы
- Подчеркивает в числовых литералах
- Новые функции ввода / вывода
- Утилиты Fork & Join / Concurrency
Монета проекта
Монета проекта, каламбур на «мелочь», содержит несколько незначительных, но полезных функций, в том числе:
Строки в выключателе
До Java 7 операторы switch работали либо с примитивными типами, либо с перечисляемыми типами. В Java 7 появился другой тип, который мы можем использовать в операторах Switch: тип String . Скажем, у нас есть требование для обработки сделки на основе поля статуса String. До сих пор мы делали это, используя операторы if-else.
|
01
02
03
04
05
06
07
08
09
10
|
private void processTrade_UsingIfs(Trade t) { String status = t.getStatus(); if (status.equalsIgnoreCase("New")) { setupNewTrade(t); } else if (status.equalsIgnoreCase("Execute")) { executeTrade(t); } else if (status.equalsIgnoreCase("Pending")) { processTrade(t); } } |
В Java7 мы можем сделать то же самое, используя оператор switch:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
public void processTrade_UsingSwitch(Trade t) { String status = t.getStatus(); switch (status) { case "New": setupNewTrade(t); break; case "Execute": executeTrade(t); break; case "Pending": processTrade(t); break; default: break; } } |
Автоматическое управление ресурсами в try-Statement
Теперь вы можете объявить ресурс в блоке try, который будет автоматически закрыт. например, раньше приходилось делать:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
public void oldTry() { FileReader fileReader = null; BufferedReader inputStream = null; try { fileReader = new FileReader("java7.txt"); inputStream = new BufferedReader(fileReader); String line = inputStream.readLine(); System.out.println(line); } catch (IOException e) { //typically log or rethrow } finally { //all resources need to be manually closed try { fileReader.close(); inputStream.close(); } catch (IOException e) { //typically ignore } } } |
Однако теперь в Java 7 оператор try-with-resources гарантирует, что каждый ресурс закрыт в конце оператора.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
public void newTry() { try ( FileReader fileReader = new FileReader("java7.txt"); BufferedReader inputStream = new BufferedReader(fileReader) ) { String line = inputStream.readLine(); System.out.println(line); } catch (IOException e) { //typically log or rethrow } //no finally block to close resources required } |
Объявление ресурсов отображается в скобках сразу после ключевого слова try.
Любой объект, который реализует java.lang.AutoCloseable, который включает все объекты, которые реализуют java.io.Closeable, может использоваться в качестве ресурса. Ресурсы будут закрыты независимо от того, завершается ли оператор try нормально или внезапно
Мульти-улов и более точное отбрасывание
Мульти поймать
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public void oldMultiCatch() { try { methodThatThrowsThreeExceptions(); } catch (ExceptionOne e) { // log and deal with ExceptionOne } catch (ExceptionTwo e) { // log and deal with ExceptionTwo } catch (ExceptionThree e) { // log and deal with ExceptionThree } } public void newMultiCatch() { try { methodThatThrowsThreeExceptions(); } catch (ExceptionOne | ExceptionTwo | ExceptionThree e) { // log and deal with all Exceptions } } public void newMultiMultiCatch() { try { methodThatThrowsThreeExceptions(); } catch (ExceptionOne e) { // log and deal with ExceptionOne } catch (ExceptionTwo | ExceptionThree e) { // log and deal with ExceptionTwo and ExceptionThree } } |
Более точный бросок
Компилятор Java SE 7 выполняет более точный анализ переброшенных исключений, позволяя вам указать более конкретные типы исключений в предложении throws объявления метода, чем те, которые используются в catch / throws тела метода.
Раньше мы должны были сделать что-то вроде этого:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
static class FirstException extends Exception { } static class SecondException extends Exception { } public void rethrowException_PreJava7(String exceptionName) throws Exception { try { if (exceptionName.equals("First")) { throw new FirstException(); } else { throw new SecondException(); } } catch (Exception e) { throw e; } } |
Обратите внимание, как мы должны были объявить более общее исключение в нашем предложении throws. В Java7 мы можем изменить это на:
|
01
02
03
04
05
06
07
08
09
10
11
|
public void rethrowException_PostJava7(String exceptionName) throws FirstException, SecondException { try { if (exceptionName.equals("First")) { throw new FirstException(); } else { throw new SecondException(); } } catch (Exception e) { throw e; } } |
Алмазный оператор
Оператор diamond упрощает вызовы конструктора, включая дженерики. Допустим, вы хотите создать карту идентификаторов строк для торговли объектами. Старый способ был бы:
|
1
|
Map<String, Trade> trades = new TreeMap<String, Trade>(); |
Но правая часть кажется немного избыточной. Может ли компилятор вывести типы, посмотрев на левую декларацию? В Java7 это может, и код становится:
|
1
|
Map<String, Trade> trades = new TreeMap<>(); |
Это приятное, но незначительное удобство — с ним уже можно было справиться, используя библиотеку Guava . Например:
|
1
|
Map<String, Trade> trades = Maps.newTreeMap(); |
Двоичные целочисленные литералы
Полезно, если вы имеете дело с двоичным кодом в вашем коде. Например, теперь вы можете сделать:
|
1
|
int three = 0b101; |
Обратите внимание на префикс 0b (или 0B), чтобы идентифицировать число как двоичный литерал.
Разрешение подчеркивания в числовых литералах
Я не думаю, что это слишком важно, но может быть полезно в некоторых обстоятельствах. например:
|
1
|
long creditCardNumber = 1234_5678_9012_3456L; |
Утилиты Fork & Join / Concurrency (JSR 166)
Инфраструктура Fork / Join фокусируется на использовании всех ресурсов обработки, доступных на машине, для повышения производительности приложений. Он предназначен для работы, которая может быть рекурсивно разбита на более мелкие части (алгоритмы «разделяй и властвуй»).
Резюме:
- Fork / Join Framework: упрощает параллельное программирование на Java
- Предназначен для многопроцессорных систем (на самом деле сегодня это практически все оборудование)
Используйте в ситуациях, когда:
- пакет работы может быть разбит на меньшие рекурсивные вызовы.
- также использует алгоритм кражи работы, при котором потоки без работы могут украсть доступную работу из других занятых потоков
Автор Дуг Ли:
- Создатель пакета oswego (стал java.util.concurrent)
- Участник Java-параллелизма на практике
Краткая история
Java 1.4 и более notifyAll() : разработка параллельных классов была очень трудной — предоставляемые низкоуровневые примитивы параллелизма ( synchronized , volatile , wait() , notifyAll() и notifyAll() ) были трудны для правильного использования, а ошибки, возникающие при использовании этих средств, затруднялись обнаружить и отладить
Java 5: включен новый пакет утилит параллелизма
Структура планирования задач — платформа Executor
Исполнитель: объект, который выполняет представленные выполняемые задачи.
ExecutorService: Executor который предоставляет методы, которые создают Future который представляет (пока не завершено) результат асинхронного вычисления.
Java 7: ForkJoinPool: новый тип ExecutorService, which позволяет executes ForkJoinTasks: одновременное выполнение обработки и рекурсивно executes ForkJoinTasks: потоковый объект, который имеет гораздо меньший вес, чем обычный поток. Огромное количество задач и подзадач может быть размещено небольшим количеством реальных потоков в ForkJoinPool.
Новый ForkJoinPool использует алгоритм «разделяй и властвуй».
Псевдокод (из статьи Дуга Ли на эту тему):
|
1
2
3
4
5
6
7
8
9
|
Result doWork(Work work) { if (work is small) { process the work } else { split up work invoke framework to solve both parts }} |
Резюме
- приятно видеть дальнейшее продвижение в Java в пространстве параллелизма, чтобы использовать все преимущества, которые мы получили в Java 5
- Потенциальные возможности использования этой структуры ограничены и требуют довольно узкого охвата проблемы.
Новые функции ввода / вывода
Java7 представила новую библиотеку файлового ввода / вывода для повышения независимости платформы и добавления поддержки метаданных и символических ссылок. Новые пакеты — это java.nio.file и java.nio.file.attribute. Основные новые классы:
- Путь : «программное представление пути в файловой системе». Вероятно, это новый класс (интерфейс), который разработчики будут использовать чаще всего. Файл, указанный по пути, не должен существовать. Для всех практических целей вы можете подумать о замене java.io.File на java. io.Path. Он включает в себя различные методы, которые можно использовать для получения информации о пути, включая создание, преобразование и сравнение путей.
- Файлы : класс Files предлагает большое количество статических методов для операций с файлами, например, для чтения, записи и управления файлами и каталогами. Методы Files работают с экземплярами объектов Path.
Это оно! Краткое изложение того, что дала нам Java7. См. Мой следующий пост в блоге для обзора некоторых новых функций в Java8.