Нове в java 8
Про все по порядку.
Default методи в інтерфейсах.
У інтерфейсах тепер можна визначати статичні методи. Справа в тому, що до Java 8 для якогось інтерфейсу, скажімо, Employee, існує клас Employees, що містить статичні методи для генерації об'єктів Employee і роботи з ними. Зручність нововведення в тому, що ці самі методи будуть знаходитися в самому інтерфейсі, а про клас Employees розробнику можна буде забути.
Як приклад подивимося на метод naturalOrder, який був доданий в java.util.Comparator
У інтерфейсах можна буде оголошувати default методи. Погляньмо на forEach в java.lang.Iterable: Default метод - це метод в інтерфейсі з реалізованої логікою, який не потрібно обов'язково визначати в реалізації цього інтерфейсу.
У попередніх версіях JDK додавати методи в інтерфейси стандартних бібліотек не представлялося можливим, це зруйнувало б весь призначений для користувача код, адже для кожної реалізації інтерфейсу довелося б дописувати реалізацію відсутнього нового методу. В Java 8 стандартні інтерфейси розширені великою кількістю default методів.
Тут варто відзначити, чому інтерфейси не реалізують default hashCode, equals і toString. Справа в тому, що об'єкти, що реалізують інтерфейс, є спадкоємцями Object, в якому вже визначені ці методи за замовчуванням. Чи стане незрозумілим, який з default методів викликати - той, що визначений в інтерфейсі, або той, що в батьківському класі.
Функціональні інтерфейси.
Функціональний інтерфейс - це той інтерфейс, який визначає тільки один абстрактний метод, як, наприклад, java.lang.Runnable:
Щоб точно визначити інтерфейс як функціональний, добавлена анотація @FunctionalInterface, що працює за принципом @Override. Вона позначить задум і не дасть визначити другий абстрактний метод в інтерфейсі.
Зауважимо, інтерфейс може включати скільки завгодно default методів і при цьому залишатися функціональним, тому що default методи - не абстрактні.
Лямбда-вирази
Саме значуще нововведення в Java 8 - це лямбда-вирази. Якщо сказати взагалі, то під ними розуміються анонімні методи, які при цьому ще вдають із себе об'єкт, який можна привласнювати змінної і передавати як аргумент в інші методи. приклад:
Тут завдяки такому лямбда-виразу ми значно скорочуємо код. Як би це виглядало без лямбда: У новій версії також введений особливий синтаксис посилань на методи, що по суті - скорочена форма деяких лямбда-виразів:
String :: valueOf x -> String.valueOf (x)
Object :: toString x -> x.toString ()
x :: toString () -> x.toString ()
ArrayList :: new () -> new ArrayList<>()
java.util.function
Ще одне нововведення JDK - безліч функціональних інтерфейсів, які будуть дуже корисні. Розглянемо деякі з них:
Function
Predicate
Consumer
Supplier
BinaryOperator
Пакет також забезпечений примітивними реалізаціями даних інтерфейсів для типів int, long і double.
java.util.stream
java.util.stream введений для підтримки розпаралелювання обчислень в потоках. Тепер потоки діляться на послідовні і паралельні. Найбільша користь від цього - в роботі з колекціями:
Stream забезпечений гнучким API для перетворення даних і оперування над ними. Ось так ми, наприклад, швидко знайдемо сумарна вага окремо червоних і синіх блоків в колекції: Що відбувається в коді:
1) З колекції blocks ми отримуємо stream
2) Метод filter повертає ще один stream, який вже містить елементи тільки одного кольору. Це проміжний (intermediate) метод класу Stream.
3) Метод mapToInt викликається у stream'а, який отриманий в пункті 2), і повертає stream, що містить не самі елементи, а їх властивості weight (тобто вага)
4) Метод sum викликається у stream'а з пункту 3), він підсумовує все weight і повертає простий int. Це кінцевий (terminal) метод, він повертає одиночний результат.
В цілому, стиль дуже схожий на той, що використовується в функціональному програмуванні, і це добре, тому що спроститься рішення широкого кола типових завдань.
Stream можна распараллелить, і тоді продуктивність операцій над ним зросте, адже навантаження розподілиться на всі ядра процесора. Давайте зробимо підрахунок елементів паралельним:
Єдина відмінність в тому, що тепер викликається метод parallelStream, і кожен наступний проміжний метод поверне паралельний stream. Таким чином, весь блок обчислень розподілиться на всі ядра процесора.
Зробити stream назад послідовним можна викликавши метод sequential (). Це в нагоді, коли нам, наприклад, потрібно, щоб відбір елементів за кольором був паралельним, а обчислення суми weight - послідовним:
Якщо ви знайомі з Joda Time, то освоїти нове API буде дуже легко. Майже всі в java.time є immutable. На відміну від старого API дати / часу, такі величини як місяці і дні тижня реалізовані через enum.
Основні класи java.time:
* LocalDateTime, LocalDate, LocalTime - представлення дати і часу. Час зберігається з точністю до наносекунди, так що в LocalTime можна зберігати, наприклад, величину "13: 45.30.123456789". Є безліч зручних методів, таких як plusMinutes, plusHours, isAfter, toSecondOfDay і т.д.
* Year, Month, YearMonth, MonthDay, DayOfWeek - типи, пов'язані з датами, отримали більший діапазон. Так, величина Year може бути від "-999,999,999" до "+999,999,999"
* Duration, Period - корисні, коли потрібно висловити дані як "3 роки, 2 місяці і 18 днів" або "3 години, 45 хвилин і 8 секунд"
На цьому нововведення Java 8 не закінчуються, а ми вивчили найочікуваніша в новій версії JDK. Всі стандартні колекції були розширені великою кількістю зручних методів і отримали можливість розпаралелювання обчислень в них з java.util.stream. Разом з java.util.function Java отримала ідіоми функціонального програмування. Лямбда-вирази, безумовно, скоротять обсяг коду, який розробникам доведеться писати, а новий API для роботи з датами і часом прийшов на заміну порядком застарілому старому.
admin liberal4ik AlexVovolka maxiflash annagrin007 ProteIne alexanzer vanya88 anastassia d3m0n1c nick_kryloff Andrey_G Cr0s dydus0x14 AngryCellophane AndrewRogovets t1oo1 san Basuliic dmytro_p Victor_MM Diesel31ks MrNikita alekseysamoylov swyd Orthodox nv_yunko