Что такое java 8
Перейти к содержимому

Что такое java 8

  • автор:

Руководство по версиям и возможностям Java

Здесь есть все, что вам нужно знать о различных версиях и функциях Java.

Java 8, Java 11, Java 13 — какая разница?

Вы можете использовать это руководство, чтобы найти и установить последнюю версию Java, понять различия между дистрибутивами Java (AdoptOpenJdk, OpenJDK, OracleJDK и т.д.), А также получить обзор возможностей языка Java, включая версии Java 8-13.

Примечание переводчика
09 апреля 2020 г. Марко опубликовал новую версию Руководства, в которую добавлено описание Java 14.
Перевод новой версии Руководства предлагается Вашему вниманию.

Исходная информация

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

Если вы хотите узнать больше о конкретной версии, перейдите на сайт AdoptOpenJDK, выберите последнюю версию Java, загрузите и установите ее. Затем вернитесь к этому руководству и узнайте еще кое-что о разных версиях Java.

Какую версию Java я должен использовать?

По состоянию на сентябрь 2019 года Java 13 является последней выпущенной версией Java, с новыми версиями, выходящими каждые 6 месяцев — Java 14 запланирована на март 2020 года, Java 15 на сентябрь 2020 года и т.д. В прошлом циклы выпуска Java были намного длиннее, до 3-5 лет!

С появлением такого количества новых версий в действительности имеются следующие основные сценарии использования:

  • Унаследованные проекты в компаниях часто связаны с использованием Java 8 (см. Раздел «Почему компании все еще застревают на Java 8?» Ниже). Таким образом, вы также будете вынуждены использовать Java 8.
  • Некоторые унаследованные проекты даже работают на Java 1.5 (выпущен в 2004 г.) или 1.6 (выпущен в 2006 г.) — сожалею, друзья!
  • Если вы уверены, что используете самые последние IDE, интегрированные среды и инструменты сборки и запускаете новый проект, вы можете без колебаний использовать Java 11 (LTS) или даже самую последнюю версию Java 13.
  • Есть специальная область разработки Android, где Java в основном застряла на версии Java 7, с доступом к определенному набору функций Java 8. Но вы можете переключиться на использование языка программирования Kotlin.

Почему компании все еще застряли на Java 8?

Существует множество разных причин, по которым компании все еще придерживаются Java 8. Вот некоторые из них:

  • Инструменты сборки (Maven, Gradle и т.д.) и некоторые библиотеки изначально имели ошибки с версиями Java версий> 8 и нуждались в обновлениях. Даже сегодня, например, с Java 9+, некоторые инструменты сборки выводят предупреждения «reflective access» при создании проектов Java, которые просто «не готовы», даже если со сборкой все в порядке.
  • До Java 8 вы в основном использовали JDK-сборки Oracle, и вам не нужно было заботиться о лицензировании. Однако в 2019 году Oracle изменила схему лицензирования, что привело к тому, что Интернет сошел с ума, сказав, что «Java больше не является бесплатной», — и последовало значительное замешательство. Однако на самом деле это не проблема, о чем вы узнаете в разделе «Дистрибутивы Java» данного руководства.
  • В некоторых компаниях действуют политики, позволяющие использовать только версии LTS, и полагаются на поставщиков своих ОС для предоставления этих сборок, что требует времени.

Подводя итог, у вас есть сочетание практических вопросов (обновление ваших инструментов, библиотек, фреймворков) и политических проблем.

Почему некоторые версии Java называются 1.X?

Java до версии 9 просто имела другую схему именования. Итак, Java 8 также может называться 1.8, Java 5 может называться 1.5 и т.д. Когда вы выполнили команду java -version с этими версиями, вы получили такой вывод:

c:\Program Files\Java\jdk1.8.0_191\bin>java -version java version "1.8.0_191" (1) Java(TM) SE Runtime Environment (build 1.8.0_191-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)

Это просто означает Java 8. С переходом к основанным на времени выпускам с Java 9 также изменилась схема именования, и версии Java больше не имеют префикса 1.x. Теперь номер версии выглядит так:

c:\Program Files\Java\jdk11\bin>java -version openjdk version "11" 2018-09-25 (1) OpenJDK Runtime Environment 18.9 (build 11+28) OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

В чем разница между версиями Java?

Должен ли я изучать конкретную?

Придя из других языков программирования с большими перерывами между выпусками, как, например, Python 2–3, вы можете спросить, применимо ли это к Java.

Java особенная в этом отношении, поскольку она чрезвычайно обратно совместима. Это означает, что ваша программа на Java 5 или 8 гарантированно будет работать с виртуальной машиной Java 8-13 — с некоторыми исключениями, о которых вам сейчас не нужно беспокоиться.

Очевидно, что это не работает наоборот, скажем, ваша программа использует функции Java 13, которые просто недоступны в Java 8 JVM.

Это означает несколько вещей:

  • Вы не просто «изучаете» конкретную версию Java, например Java 12.
  • Скорее, вам нужно получить хорошую основу для всех языковых возможностей вплоть до Java 8.
  • И затем, из этого руководства вы можете узнать, какие дополнительные функции появились в Java 9-13, чтобы использовать их всегда, когда это возможно.

Каковы примеры этих новых возможностей новых версий Java?

Взгляните на раздел «Возможности Java 8-13» ниже.

Но, как правило: старые, более длинные циклы выпуска (3-5 лет, вплоть до Java 8) означали множество новых функций в каждом выпуске.

Шестимесячный цикл выпуска означает меньшее количество функций на выпуск, поэтому вы можете быстро освоить языковые функции Java 9-13.

В чем разница между JRE и JDK?

До сих пор мы говорили только о Java. Но что именно означает «Java»?

Во-первых, вам нужно провести различие между JRE (Java Runtime Environment) и JDK (Java Development Kit).

Исторически, вы загружали только JRE, если вас интересовали только программы Java. JRE включает, помимо прочего, виртуальную машину Java (JVM) и инструмент командной строки «java».

Для разработки новых программ на Java вам нужно было загрузить JDK. JDK включает в себя все, что есть в JRE, а также компилятор javac и несколько других инструментов, таких как javadoc (генератор документации Java) и jdb (отладчик Java).

Теперь, почему я говорю в прошедшем времени?

Вплоть до Java 8 веб-сайт Oracle предлагал JRE и JDK в качестве отдельных загрузок, хотя JDK также всегда включал JRE в отдельной папке. В Java 9 это различие практически исчезло, и вы всегда загружаете JDK. Структура каталогов JDK также изменилась, так как в ней больше не было явной папки JRE.

Таким образом, хотя некоторые дистрибутивы (см. Раздел «Дистрибутивы Java») по-прежнему предлагают отдельную загрузку JRE, похоже, существует тенденция предлагать только JDK. Следовательно, теперь мы будем использовать Java и JDK взаимозаменяемо.

Как мне установить Java или JDK?

На данный момент не обращайте внимания на образы Java-Docker, оболочки MSI или пакеты для конкретной платформы. В конце концов, Java — это просто файл .zip; ни больше ни меньше.

Поэтому все, что вам нужно сделать, чтобы установить Java на свой компьютер, — это разархивировать файл jdk-.zip. Вам даже не нужны права администратора для этого.

Ваш распакованный файл Java будет выглядеть так:

Directory C:\dev\jdk-11 12.11.2019 19:24 . 12.11.2019 19:24 .. 12.11.2019 19:23 bin 12.11.2019 19:23 conf 12.11.2019 19:24 include 12.11.2019 19:24 jmods 22.08.2018 19:18 legal 12.11.2019 19:24 lib 12.11.2019 19:23 1.238 release

Магия происходит в каталоге / bin, который в Windows выглядит следующим образом:

Directory C:\dev\jdk-11\bin . 12.11.2019 19:23 272.736 java.exe . 12.11.2019 19:23 20.832 javac.exe . 

Поэтому все, что вам нужно сделать, это разархивировать этот файл и поместить каталог /bin в переменную PATH, чтобы вы могли вызывать команду java из любого места.

В случае, если вам интересно, установщики с графическим интерфейсом, такие как Oracle или AdoptOpenJDK, выполняет распаковку и изменение переменной PATH вместо вас.

Чтобы убедиться, что вы правильно установили Java, вы можете просто выполнить команду java -version. Если вывод выглядит так, как показано ниже, вы готовы!

openjdk version "11" 2018-09-25 OpenJDK Runtime Environment 18.9 (build 11+28) OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

Теперь остался один вопрос: откуда вам взять этот .zip файл с Java? Что подводит нас к теме дистрибутивов.

Дистрибутивы Java

Существует множество сайтов, предлагающих загрузку Java (читай: JDK), и неясно, «кто что предлагает и с каким лицензированием». Этот раздел проливает свет на это.

Проект OpenJDK

С точки зрения исходного кода Java (читай: исходный код вашего JRE / JDK) есть только один — на сайте проекта OpenJDK.

Однако это всего лишь исходный код, а не распространяемая сборка (подумайте: ваш файл .zip с скомпилированной командой java для вашей конкретной операционной системы). Теоретически вы и я могли бы создать сборку из этого исходного кода, назвать ее, скажем, MarcoJDK, и начать ее дистрибуцию. Но наш дистрибутив не будет сертифицирован, чтобы можно было называть этот дистрибутив совместимым с Java SE.

Вот почему на практике есть несколько поставщиков, которые фактически создают эти сборки, сертифицируют (см. TCK) и затем распространяют их.

И хотя поставщики не могут, скажем, удалить метод из класса String перед созданием новой сборки Java, они могут добавить брэндинг (вay!) или добавить некоторые другие утилиты (например, CLI), которые они считают полезными. Но в остальном исходный код одинаков для всех дистрибутивов Java.

OpenJDK (от Oracle) и сборки OracleJDK

Один из поставщиков, который создает Java из исходного кода, — это Oracle. Это приводит к двум разным дистрибутивам Java, что поначалу может быть очень запутанными.

  1. Сборки OpenJDK от Oracle (!). Эти сборки бесплатны и не имеют торговой марки, но Oracle не выпустит обновления для более старых версий, скажем, Java 13, как только выйдет Java 14.
  2. OracleJDK — это коммерческая сборка под брендом, выпускаемая начиная с изменения лицензии в 2019 году. Это означает, что ее можно использовать бесплатно во время разработки, но вы должны платить Oracle, если используете ее в рабочей среде. При этом вы получаете более длительную поддержку, то есть все обновления дистрибутива и номер телефона, по которому можно позвонить, если с вашей JVM будут проблемы.

Исторически (до Java 8) существовали реальные исходные различия между сборками OpenJDK и сборками OracleJDK, при этом можно было сказать, что OracleJDK был «лучше». Но на сегодняшний день обе версии практически одинаковы, с небольшими отличиями.

Впрочем все сводится к тому, что вам требуется платная коммерческая поддержка (номер телефона) для используемой версии Java.

AdoptOpenJDK

В 2017 году группа участников, разработчиков и поставщиков Java User Group (Amazon, Microsoft, Pivotal, Red Hat и другие) создала сообщество под названием AdoptOpenJDK.

Они предоставляют бесплатные надежные сборки OpenJDK с более длительной доступностью / обновлениями и даже предлагают вам выбор из двух разных виртуальных машин Java: HotSpot и OpenJ9.

Я очень рекомендую ее, если вы хотите установить Java.

Azul Zulu, Amazon Corretto, SAPMachine

Полный список сборок OpenJDK вы найдете на сайте OpenJDK Wikipedia. Среди них Azul Zulu, Amazon Corretto, а также https://sap.github.io/SapMachine/ и многие другие. Упрощенно говоря, различия сводятся к тому, что у вас есть различные варианты поддержки/ гарантии обслуживания.

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

Рекомендация

Повторим с еще раз, что с 2019 года, если у вас нет особых требований, найдите файл jdk.zip (.tar.gz/.msi/.pkg) по адресу https://adoptopenjdk.net или выберите пакет, предоставленный вашим поставщиком ОС.

Возможности Java 8-13

Как уже упоминалось в самом начале этого руководства: в сущности все (если вы не будьте слишком требовательны) функции языка Java 8 работают в Java 13. То же самое касается всех других версий Java между ними.

В свою очередь, это означает, что знание всех языковых функций Java 8 дает хорошую базу в изучении Java, а все остальные версии (Java 9-13) в значительной степени дают дополнительные функции поверх этого базового уровня.

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

Java 8

Java 8 была массовым выпуском, и вы можете найти список всех функций на веб-сайте Oracle. Здесь я хотел бы упомянуть два основных набора функций:

Особенности языка: лямбды и т.д.

До Java 8 всякий раз, когда вы хотели создать экземпляр, например, нового Runnable, вы должны были написать анонимный внутренний класс, например, так:

 Runnable runnable = new Runnable() < @Override public void run()< System.out.println("Hello world !"); >>;

С лямбдами тот же код выглядит так:

Runnable runnable = () -> System.out.println("Hello world two!");

Вы также получили ссылки на методы, повторяющиеся аннотации, методы по умолчанию для интерфейсов и некоторые другие языковые функции.

Коллекции и потоки

В Java 8 вы также получили операции в функциональном стиле для коллекций, также известные как Stream API. Быстрый пример:

List list = Arrays.asList("franz", "ferdinand", "fiel", "vom", "pferd");

До Java 8, вам нужно было написать циклы for, чтобы что-то сделать с этим списком.

С помощью API Streams вы можете сделать следующее:

list.stream() .filter(name -> name.startsWith("f")) .map(String::toUpperCase) .sorted() .forEach(System.out::println);

Java 9

Java 9 также была довольно большой версией, с несколькими дополнениями:

Коллекции

Коллекции получили несколько новых вспомогательных методов для простого создания списков, наборов и карт.

List list = List.of("one", "two", "three"); Set set = Set.of("one", "two", "three"); Map map = Map.of("foo", "one", "bar", "two");
Streams

Потоки получили несколько дополнений, в виде методов takeWhile, dropWhile и iterate.

Stream stream = Stream.iterate("", s -> s + "s") .takeWhile(s -> s.length() < 10);
Optionals

Optionals получили метод ifPresentOrElse, которого крайне не хватало.

user.ifPresentOrElse(this::displayAccount, this::displayLogin);
Интерфейсы

Интерфейсы получили private методы:

public interface MyInterface < private static void myPrivateMethod()< System.out.println("Yay, I am private!"); >>
Другие возможности языка

И пара других улучшений, таких как улучшенный оператор try-with-resources или расширения diamond оператора.

JShell

Наконец, в Java появилась оболочка, в которой вы можете попробовать простые команды и получить немедленные результаты.

% jshell | Welcome to JShell -- Version 9 | For an introduction type: /help intro jshell> int x = 10 x ==> 10
HTTPClient

Java 9 принес первоначальную предварительную версию нового HttpClient. До этого встроенная поддержка Http в Java была довольно низкоуровневой, и вам приходилось использовать сторонние библиотеки, такие как Apache HttpClient или OkHttp (кстати, отличные библиотеки).

В Java 9 у Java появился собственный современный клиент — хотя он находится в режиме превью, что означает, что он может быть изменен в более поздних версиях Java.

Проект Jigsaw: модули Java и файлы Jar с несколькими выпусками

Java 9 получила Jigsaw Module System, которая чем-то напоминает старую добрую спецификацию OSGI. Целью данного руководства не является подробное описание Jigsaw — посмотрите предыдущие ссылки, чтобы узнать больше.

Файлы Multi-Release .jar позволили создать один файл .jar, содержащий разные классы для разных версий JVM. Таким образом, ваша программа может вести себя по-разному / иметь разные классы, используемые при запуске на Java 8 и на Java 10, например.

Java 10

В Java 10 было несколько изменений, таких как сборка мусора и т.д. Но единственное реальное изменение, которое вы, как разработчик, вероятно, заметите, — это введение ключевого слова var, также называемого выводом типа локальной переменной.

Вывод типа локальной переменной: ключевое слово var

// Pre-Java 10 String myName = "Marco"; // With Java 10 var myName = "Marco"

Чувствуете себя как в Javascript-е, не так ли? Однако Java все еще строго типизирован и var применяется только к переменным внутри методов (спасибо, dpash, за то, что снова указал на это).

Java 11

Java 11 также была несколько меньшей версией с точки зрения разработчика.

Строки и файлы

Строки и файлы получили несколько новых методов (не все перечислены здесь):

"Marco".isBlank(); "Mar\nco".lines(); "Marco ".strip(); Path path = Files.writeString(Files.createTempFile("helloworld", ".txt"), "Hi, my name is!"); String s = Files.readString(path);
Запустить исходные файлы

Начиная с Java 10, вы можете запускать исходные файлы Java без предварительной компиляции. Шаг к написанию сценариев.

ubuntu@DESKTOP-168M0IF:~$ java MyScript.java
Вывод типа локальной переменной (var) для лямбда-параметров

В заголовке все сказано:

(var firstName, var lastName) -> firstName + lastName
HttpClient

HttpClient из Java 9, но уже в окончательной, а не превью версии.

Другие вкусности

Flight Recorder (Регистратор полетов), сборщик мусора No-Op, Nashorn-Javascript-Engine объявлен deprecated (устаревшим) и т.д.

Java 12

В Java 12 появилось несколько новых функций и исправлений, но здесь стоит упомянуть только поддержку Unicode 11 и превью нового выражения switch, о котором вы узнаете в следующем разделе.

Java 13

Вы можете найти полный список возможностей здесь, но, по сути, вы получаете поддержку Unicode 12.1, а также две новые или улучшенные превью функции (могут быть изменены в будущем):

Switch выражение (Preview — предварительная версия)

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

Старые операторы switch выглядели так:

switch(status) < case SUBSCRIBER: // code block break; case FREE_TRIAL: // code block break; default: // code block >

В то время как в Java 13 операторы switch могут выглядеть так:

boolean result = switch (status) < case SUBSCRIBER ->true; case FREE_TRIAL -> false; default -> throw new IllegalArgumentException("something is murky!"); >;
Многострочные строки (превью)

Наконец-то вы можете сделать это на Java:

String htmlBeforeJava13 + " \n" + " 

Hello, world

\n" + " \n" + "\n"; String htmlWithJava13 = """

Hello, world

""";

Java 14 и позже

Будет рассмотрено здесь, как только их выпустят. Зайдите в ближайшее время!

Вывод

К настоящему времени у вас должен быть довольно хорошее представление о нескольких вещах:

  • Как установить Java, какую версию получить и где ее получить (подсказка: AdoptOpenJDK).
  • Что такое дистрибутив Java, какие существуют и в чем различия.
  • Каковы различия между конкретными версиями Java.

Обратная связь, исправления и случайный ввод всегда приветствуются! Просто оставьте комментарий внизу.

Спасибо за прочтение!

Там больше, откуда это появилось

Эта статья первоначально появилась на сайте как часть серии руководств по современному программированию на Java. Чтобы найти больше руководств, посетите веб-сайт или подпишитесь на рассылку, чтобы получать уведомления о недавно опубликованных руководствах: https://bit.ly/2K0Ao4F.

Благодарности

Стивен Колебурн написал фантастическую статью о различных доступных дистрибутивах Java. Спасибо, Стивен!

Что такое java 8

Cloud Account Sign in to Cloud Sign Up for Free Cloud Tier

Java 8 is a revolutionary release of the world’s #1 development platform. It includes a huge upgrade to the Java programming model and a coordinated evolution of the JVM, Java language, and libraries. Java 8 includes features for productivity, ease of use, improved polyglot programming, security and improved performance. Welcome to the latest iteration of the largest, open, standards-based, community-driven platform.

Java ME 8 is now Generally Available-Java ME 8 is an ideal platform for intelligent devices and an optimal foundation for developers to build new services for the IoT.

Downloads

  • Java ME Embedded 8
  • Java ME SDK 8
  • JDK 8
  • Java SE Embedded

Documentation

Features

Productivity

Class Optional

  • Tired of Null Pointer Exceptions? Consider Using Java SE 8's Optional! by Raoul-Gabriel Urma
  • Make your code more readable and protect it against null pointer exceptions.

Lambdas

  • NightHacking Worldwide: Lambdas Part 1, Presentation
  • NightHacking Worldwide: Lambdas Part 2, Q&A
  • Java 8 Lambdas Pragmatic Functional Programming by Richard Warburton (Early Access Edition)
  • This book shows you how to make use of your existing skills to adapt your thinking and codebase to use Lambda expressions properly.

Особенности Java 8 – максимальное руководство (часть 1)

Java-университет

Особенности Java 8 – максимальное руководство (часть 1) - 1

Первая часть перевода статьи Java 8 Features – The ULTIMATE Guide. Вторая часть тут (ссылка может поменяться). От редакции: статья опубликована в то время как Java 8 была доступна общественности и все указывает на то, что это действительно major-версия. Здесь мы в изобилии предоставили руководства Java Code Geeks, такие как Играем с Java 8 – Лямбды и Параллелизм, Java 8 руководство по API даты и времени: LocalDateTime и Абстрактный Класс против Интерфейса в эру Java 8. Мы также ссылаемся на 15 необходимых к прочтению руководств по Java 8 из других источников. Конечно мы рассматриваем некоторые из недостатков, например, Темная сторона Java 8. Итак, пришло время собрать все основные особенности Java 8 в одном месте для вашего удобства. Наслаждайтесь!

1. Введение

  • Язык
  • Компилятор
  • Библиотеки
  • Инструменты
  • Среда выполнения (JVM)

2. Новые особенности в языке Java 8

В любом случае Java 8 – это крупный релиз. Можно сказать, что это заняло так много времени из-за реализации возможностей, которые искал каждый Java-разработчик. В этом разделе мы собираемся охватить большинство из них.

2.1. Лямбды и Функциональные интерфейсы

Лямбды (также известные как закрытые или анонимные методы) наиболее большое и наиболее ожидаемое изменение языка во всем релизе Java 8. Они позволяют нам задавать функциональность как аргумент метода (объявляя функцию вокруг), или задавать код как данные: понятия с которыми знаком каждый разработчик функционального программирования. Много языков на платформе JVM (Groovy, Scala, …) имели лямбды с первого дня, но у разработчиков Java не было выбора кроме как представлять лямбды через анонимные классы. Обсуждение дизайна лямбд заняли много времени и усилий общественности. Но в конце концов компромиссы были найдены, что привело к появлению новых кратких конструкций. В своей простейшей форме лямбда может быть представлена в виде разделенных запятыми списка параметров, символа –> и тела. Например:

 Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) ) 

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

 Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.println( e ) ); 

В случае, если тело лямбды более сложное, оно может быть обернуто в фигурные скобки подобно определению обычной функции в Java. Например:

 Arrays.asList( "a", "b", "d" ).forEach( e - < < System.out.print( e ); System.out.print( e ); >); 

Лямбда может ссылаться на члены класса и локальные переменные (неявно делает обращение эффективным независимо от того обращается к final полю или нет). Например, эти 2 фрагмента эквиваленты:

 String separator = ","; Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.print( e + separator ) ); 
 final String separator = ","; Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.print( e + separator ) ); 

Лямбды могут возвращать значение. Тип возвращаемого значения будет определен компилятором. Объявление return не требуется, если тело лямбды состоит из одной строки. Два фрагмента кода ниже эквивалентны:

 Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) ); 
 Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> < int result = e1.compareTo( e2 ); return result; >); 

Разработчики языка долго думали как сделать уже существующие функции лямбда-дружелюбными. В результате появилось понятие функционального интерфейса. Функциональный интерфейс – это интерфейс с только одним методом. В результате он может быть неявно преобразован в лямбда-выражение. java.lang.Runnable и java.util.concurrent.Callable два замечательных примера функциональных интерфейсов. На практике функциональные интерфейсы очень хрупки: если кто-то добавит хотя бы один другой метод в определение интерфейса, он не будет больше функциональным и процесс компиляции не завершится. Чтобы избежать этой хрупкости и явно определить намерения интерфейса как функционального в Java 8 была добавлена специальная аннотация @FunctionalInterface (все существующие интерфейсы в библиотеке Java получили аннотацию @FunctionalInterface). Давайте посмотрим на это простое определение функционального интерфейса:

 @FunctionalInterface public interface Functional

Есть одна вещь, которую нужно иметь в виду: методы по умолчанию и статические методы не нарушают принцип функционального интерфейса и могут быть объявлены:

 @FunctionalInterface public interface FunctionalDefaultMethods < void method(); default void defaultMethod() < >> 

Лямбды наиболее популярный пункт Java 8. Они имеют весь потенциал для привлечения большего количества разработчиков к этой прекрасной платформе и обеспечить умелую поддержку функциональным особенностям в чистой Java. Для более детальной информации обратитесь к официальной документации.

2.2. Интерфейсы по умолчанию и статические методы

В Java 8 было расширено определение интерфейсов двумя новыми концепциями: метод по умолчанию и статический метод. Методы по умолчанию делают интерфейсы несколько похожими на трейты, но служат немного другой цели. Они позволяют добавлять новые методы к существующим интерфейсам не нарушая обратную совместимость для ранее написанных версий этих интерфейсов. Разница между методами по умолчанию и абстрактными методами в том, что абстрактные методы должны быть реализованы, а методы по умолчанию нет. Вместо этого каждый интерфейс должен предоставить так называемую реализацию по умолчанию, и все наследники будут получать ее по умолчанию (с возможностью переопределить эту реализацию по умолчанию при необходимости). Давайте посмотрим на пример ниже.

 private interface Defaulable < // Интерфейсы теперь разрешают методы по умолчанию, // клиент может реализовывать (переопределять) // или не реализовывать его default String notRequired() < return "Default implementation"; >> private static class DefaultableImpl implements Defaulable < >private static class OverridableImpl implements Defaulable < @Override public String notRequired() < return "Overridden implementation"; >> 

Интерфейс Defaulable объявил метод по умолчанию notRequired() используя ключевое слово default как часть определения метода. Один из классов, DefaultableImpl , реализует этот интерфейс оставляя метод по умолчанию как есть. Другой класс, OverridableImpl , переопределяет реализацию по умолчанию и предоставляет свою собственную. Другая интересная особенность, представленная в Java 8 – это то, что интерфейсы могут объявить (и предложить реализацию) статических методов. Вот пример:

 private interface DefaulableFactory < // Interfaces now allow static methods static Defaulable create( Suppliersupplier ) < return supplier.get(); >> 

Небольшой фрагмент кода объединяет метод по умолчанию и статический метод из примера выше:

 public static void main( String[] args )

Вывод на консоль этой программы выглядит так:

 Default implementation Overridden implementation 

Реализация методов по умолчанию в JVM является очень эффективной и вызов метода поддерживается инструкциями байт-кода. Методы по умолчанию позволили существующим Java интерфейсам развиваться не нарушая процесс компиляции. Хорошие примеры – множество добавленных методов в интерфейс java.util.Collection : stream() , parallelStream() , forEach() , removeIf() , … Хотя будучи мощными, методы по умолчанию следует использовать с осторожностью: прежде, чем объявить метод по умолчанию стоит подумать дважды действительно ли это необходимо так как это может привести к неоднозначности компиляции и ошибках в сложных иерархиях. Для получения более детальной информации обращайтесь к документации.

2.3. Ссылочные методы

Ссылочные методы внедряют полезный синтаксис, чтобы ссылаться на существующие методы или конструкторы Java-классов или объектов (экземпляров). Совместно с лямбда-выражениями, ссылочные методы делают языковые конструкции компактными и лаконичными, делая его шаблонным. Ниже представлен класс Car как пример различных определений методов, давайте выделим четыре поддерживаемых типа ссылочных методов:

 public static class Car < public static Car create( final Suppliersupplier ) < return supplier.get(); >public static void collide( final Car car ) < System.out.println( "Collided " + car.toString() ); >public void follow( final Car another ) < System.out.println( "Following the " + another.toString() ); >public void repair() < System.out.println( "Repaired " + this.toString() ); >> 

Первый ссылочный метод – ссылка на конструктор с синтаксисом Class::new или альтернативный для дженериков (generics) Class< T >::new . Обратите внимание, что конструктор не имеет аргументов.

 final Car car = Car.create( Car::new ); final List cars = Arrays.asList( car ); 

Второй вариант это ссылка на статический метод с синтаксисом Class::static_method . Обратите внимание, что метод принимает ровно один параметр типа Car .

 cars.forEach( Car::collide ); 

Третий тип – ссылка на метод экземпляра произвольного объекта определенного типа с синтаксисом Class::method . Обратите внимание, что никакие аргументы не принимаются методом.

 cars.forEach( Car::repair ); 

И последний, четвертый тип – ссылка на метод экземпляра определенного класса с синтаксисом instance::method . Обратите внимание, что метод принимает только один параметр типа Car .

 final Car police = Car.create( Car::new ); cars.forEach( police::follow ); 

Запуск всех этих примеров как Java-программы производит следующий вывод на консоль (ссылка на класс Car может отличаться):

 Collided com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d Repaired com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d Following the com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d 

Для более детальной информации и деталей ссылочных методов обращайтесь к официальной документации.

2.4. Повторяющиеся аннотации

С тех пор как в Java 5 была введена поддержка аннотаций, эта возможность стала очень популярной и очень широко используемой. Тем не менее, одним из ограничений использования аннотаций был тот факт, что одна и та же аннотация не может быть объявлена более одного раза в одном месте. Java 8 нарушает это правило и представляет повторяющиеся аннотации. Это позволяет тем же аннотациям повторяться несколько раз в том месте где они объявлены. Повторяющиеся аннотации следует аннотировать себя с использованием аннотации @Repeatable . На самом деле, это не сколько изменение языка сколько трюк компилятора, в то время как техника остается той же. Давайте посмотрим на простой пример:

 package com.javacodegeeks.java8.repeatable.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; public class RepeatingAnnotations < @Target( ElementType.TYPE ) @Retention( RetentionPolicy.RUNTIME ) public @interface Filters < Filter[] value(); >@Target( ElementType.TYPE ) @Retention( RetentionPolicy.RUNTIME ) @Repeatable( Filters.class ) public @interface Filter < String value(); >; @Filter( "filter1" ) @Filter( "filter2" ) public interface Filterable < >public static void main(String[] args) < for( Filter filter: Filterable.class.getAnnotationsByType( Filter.class ) ) < System.out.println( filter.value() ); >> > 

Как мы можем видеть, класс Filter аннотирован с помощью @Repeatable( Filters. class ). Filters просто владелец аннотаций Filter , но компилятор Java старается скрыть их присутствие от разработчиков. Таким образом, интерфейс Filterable содержит аннотации Filter , которые объявлены дважды (без упоминания Filters ). Также Reflection API предоставляет новый метод getAnnotationsByType() для возвращения повторяющихся аннотаций некоторого типа (помните, что Filterable. class .getAnnotation( Filters. class ) вернет экземпляр Filters введенный компилятором). Вывод программы будет выглядеть следующим образом:

 filter1 filter2 

За более детальной информацией обратитесь к официальной документации.

2.5. Улучшенное выведение типов

Компилятор Java 8 получил много улучшений выведения типов. Во многих случаях явные параметры типов могут быть определены компилятором, тем самым делая код чище. Давайте взглянем на один из примеров:

 package com.javacodegeeks.java8.type.inference; public class Value  < public staticT defaultValue() < return null; >public T getOrDefault( T value, T defaultValue ) < return ( value != null ) ? value : defaultValue; >> 

А вот использование с типом Value :

 package com.javacodegeeks.java8.type.inference; public class TypeInference < public static void main(String[] args) < final Valuevalue = new Value<>(); value.getOrDefault( "22", Value.defaultValue() ); > > 

Параметр типа Value.defaultValue() определеляется автоматически и не должен быть представлен явно. В Java 7 тот же пример не будет компилироваться и должен быть переписан в виде Value.defaultValue().

2.6. Расширенная поддержка аннотаций

Java 8 расширяет контекст где могут быть использованы аннотации. Сейчас аннотацию может иметь почти все: локальные переменные, обобщенные типы, суперклассы и реализуемые интерфейсы, даже исключения методов. Несколько примеров представлено ниже:

 package com.javacodegeeks.java8.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.ArrayList; import java.util.Collection; public class Annotations < @Retention( RetentionPolicy.RUNTIME ) @Target( < ElementType.TYPE_USE, ElementType.TYPE_PARAMETER >) public @interface NonEmpty < >public static class Holder extends @NonEmpty Object < public void method() throws @NonEmpty Exception < >> @SuppressWarnings( "unused" ) public static void main(String[] args) < final Holderholder = new @NonEmpty Holder(); @NonEmpty Collection strings = new ArrayList<>(); > > 

ElementType.TYPE_USE и ElementType.TYPE_PARAMETER два новых типа элементов, чтобы описать соответствующий контекст аннотаций. Annotation Processing API также потерпело незначительные изменения, чтобы распознать новые типы аннотаций в Java.

3. Новые возможности в компиляторе Java

3.1. Имена параметров

На протяжении всего времени разработчики Java изобретали разнообразные способы сохранения имен параметров метода в Java байт-коде, чтобы сделать их доступными во время выполнения (например, библиотека Paranamer). И наконец, Java 8 создает эту нелегкую функцию в языке (используя Reflection API и метод Parameter.getName() ) и байт-коде (с помощью нового аргумента компилятора javac : –parameters ).

 package com.javacodegeeks.java8.parameter.names; import java.lang.reflect.Method; import java.lang.reflect.Parameter; public class ParameterNames < public static void main(String[] args) throws Exception < Method method = ParameterNames.class.getMethod( "main", String[].class ); for( final Parameter parameter: method.getParameters() ) < System.out.println( "Parameter: " + parameter.getName() ); >> > 

Если вы скомпилируете этот класс без использования аргумента –parameters и затем запустите программу, вы увидите что-то типа этого:

 Parameter: arg0 

С параметром –parameters переданным компилятору, вывод программы будет отличаться (будет показано фактическое имя параметра):

 Parameter: args 

Для опытных пользователей Maven аргумент –parameters может быть добавлен в компиляцию используя секцию maven-compiler-plugin :

  org.apache.maven.plugins maven-compiler-plugin 3.1 -parameters 1.8 1.8   

Для проверки доступности имен параметров есть удобный isNamePresent() метод предоставленный классом Parameter .

4. Новые инструменты Java

Java 8 поставляется с новым набором инструментов командной строки. В этом разделе мы рассмотрим самые интересные из них.

4.1. Движок Nashorn: jjs

jjs – автономный движок Nashorn, который основан на командной строке. Он принимает список JavaScript файлов исходного кода и запускает их. Например, давайте создадим файл func.js следующего содержания:

 function f() < return 1; >; print( f() + 1 ); 

Чтобы запустить этот файл давайте передадим его как аргумент в jjs:

 jjs func.js 

Вывод на консоль будет таким:
Для более подробной информации смотрите документацию.

4.2. Анализатор зависимостей класса: jdeps

jdeps действительно отличный инструмент командной строки. Он показывает зависимости на уровне пакета или класса для Java классов. Он принимает .class файл, папку или JAR-файл на вход. По умолчанию jdeps выводит зависимости в стандартную систему вывода (консоль). В качестве примера давайте посмотрим на отчет зависимостей популярной библиотеки Spring Framework. Чтоб сделать пример коротким давайте посмотрим зависимости только для JAR-файла org.springframework.core-3.0.5.RELEASE.jar .

 jdeps org.springframework.core-3.0.5.RELEASE.jar 

Эта команда выводит довольно много, поэтому мы будем анализировать только часть вывода. Зависимости сгруппированы по пакетам. Если зависимостей нет – будет выведено not found.

 org.springframework.core-3.0.5.RELEASE.jar -> C:\Program Files\Java\jdk1.8.0\jre\lib\rt.jar org.springframework.core (org.springframework.core-3.0.5.RELEASE.jar) -> java.io -> java.lang -> java.lang.annotation -> java.lang.ref -> java.lang.reflect -> java.util -> java.util.concurrent -> org.apache.commons.logging not found -> org.springframework.asm not found -> org.springframework.asm.commons not found org.springframework.core.annotation (org.springframework.core-3.0.5.RELEASE.jar) -> java.lang -> java.lang.annotation -> java.lang.reflect -> java.util 

Java 8

Наконец-то появилась поддержка Java 8. С чем его едят?

Android всегда запаздывала с поддержкой новых версий Java. Когда уже была Java 7, официально поддерживалась версия Java 6, хотя многие пользовались седьмой версией на свой страх и риск. В целом проблем не было, если не использовались некоторые специфические новинки. Затем поддержку седьмой версии подтвердили официально.

Та же история повторяется с версией Java 8.

Убедитесь, что у вас установлена Java 8. Если вы устанавливали Android Studio с нуля, начиная с версии 2.2, то по умолчанию студия устанавливает в своей папке jre специальную версию OpenJDK, которая является альтернативой JDK от Oracle. Вы можете использовать любые из этих версий, хотя рекомендуется использовать первый вариант.

В Android Studio 4.0 поддержка Java 8 расширилась.

В документации показан следующий способ. Создаём новый проект. В build.gradle проекта в секцию android добавляем следующие записи.

 android < defaultConfig < // Required when setting minSdkVersion to 20 or lower multiDexEnabled true >compileOptions < // Flag to enable support for the new language APIs coreLibraryDesugaringEnabled true // Sets Java compatibility to Java 8 sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 >> dependencies

Также можно это сделать через настройки студии в меню File | Project Structure, используя раздел app. На вкладке Properties установите версии 1.8 для опций Source Compatibility и Target Compatibility.

Теперь вы можете использовать новые возможности, предоставляемые Java 8.

Поддержка Java 8 не является полной. Подробнее можно посмотреть на странице https://developer.android.com/studio/write/java8-support.html#supported_features.

Новое в Java 8

default

Методы интерфейсов по умолчанию. Java 8 позволяет вам добавлять неабстрактные реализации методов в интерфейс, используя ключевое слово default.

 interface Formula < double calculate(int a); default double sqrt(int a) < return Math.sqrt(a); >> 

Кроме абстрактного метода calculate() интерфейс Formula также определяет метод по умолчанию sqrt(). Классы, имплементирующие этот интерфейс, должны переопределить только абстрактный метод calculate(). Метод по умолчанию sqrt() будет доступен без переопределения.

 Formula formula = new Formula() < @Override public double calculate(int a) < return sqrt(a * 100); >>; formula.calculate(100); // 100.0 formula.sqrt(16); // 4.0 

Predicate/Предикаты

Предикаты (predicate) — это функции-коты, принимающие один аргумент, и возвращающие значение типа boolean. Интерфейс содержит различные методы по умолчанию, позволяющие строить сложные условия (and, or, negate).

 Predicate predicate = (s) -> s.length() > 0; predicate.test("foo"); // true predicate.negate().test("foo"); // false Predicate nonNull = Objects::nonNull; Predicate isNull = Objects::isNull; Predicate isEmpty = String::isEmpty; Predicate isNotEmpty = isEmpty.negate(); 

Предикаты могут входить в состав метода в качестве параметра. Смотри пример метода ArrayList.removeIf().

Function/Функции

Функции принимают один аргумент и возвращают некоторый результат. Методы по умолчанию могут использоваться для построения цепочек вызовов (compose, andThen).

 Function toInteger = Integer::valueOf; Function backToString = toInteger.andThen(String::valueOf); backToString.apply("123"); // "123" 

Supplier/Поставщики

Поставщики (suppliers) предоставляют результат заданного типа. В отличии от функций, поставщики не принимают аргументов.

 Supplier personSupplier = Person::new; personSupplier.get(); // new Person 

Consumer/Потребители

Потребители (consumers) представляют собой операции, которые производятся с одним входным аргументом.

 Consumer greeter = (p) -> System.out.println("Hello, " + p.firstName); greeter.accept(new Person("Luke", "Skywalker")); 

Comparator/Компараторы

Компараторы хорошо известны по предыдущим версиям Java. Java 8 добавляет в интерфейс различные методы по умолчанию.

 Comparator comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName); Person p1 = new Person("John", "Doe"); Person p2 = new Person("Alice", "Wonderland"); comparator.compare(p1, p2); // > 0 comparator.reversed().compare(p1, p2); // < 0 

Другое

Дополнительные материалы

Java 8+ APIs available through desugarin - список поддерживаемых методов из Java 8.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *