interface enhancements java 8 java functional interface
Цей посібник пояснює доповнення до інтерфейсу в Java 8 та відмінності між такими поняттями Java, як абстрактний клас, розширення ключового слова тощо за допомогою інтерфейсів:
Ми досліджували все про Інтерфейси в Java в нашому останньому уроці. Ми представили та висвітлили основні поняття інтерфейсів у Java, включаючи численні інтерфейси.
До Java 8 інтерфейсам дозволялося мати лише абстрактні методи та статичні та кінцеві змінні. Абстрактні методи за замовчуванням є загальнодоступними і повинні бути замінені класом, який реалізує інтерфейс.
Таким чином, інтерфейс в основному був контрактом і був задіяний лише з константами (статичними та кінцевими) та абстрактними методами.
=> Подивіться тут посібник для початківців Java.
Що ви дізнаєтесь:
- Зміни інтерфейсів у Java 8
- Функціональні інтерфейси Java 8
- Інтерфейс класу проти Java
- Java розширює реалізації Vs
- Інтерфейс проти абстрактного класу в Java
- Висновок
Зміни інтерфейсів у Java 8
Випуск Java 8 вводить або дозволяє нам мати статичні та стандартні методи в інтерфейсах. Використовуючи методи інтерфейсу за замовчуванням, розробники можуть додати до інтерфейсів більше методів. Таким чином вони не заважають і не змінюють класи, що реалізують інтерфейс.
Java 8 також дозволяє інтерфейсу мати статичний метод. Статичні методи такі ж, як і ті, що ми визначаємо в класах. Зверніть увагу, що статичний метод не може бути замінений класом, який реалізує інтерфейс.
Введення в інтерфейс статичних методів та методів за замовчуванням полегшило зміну інтерфейсів без будь-яких проблем, а також спростило реалізацію інтерфейсів.
Java 8 також вводить «лямбда-вирази» всередину функціональних інтерфейсів. Крім того, починаючи з Java 8, в Java додаються більше вбудованих функціональних інтерфейсів.
У цьому посібнику ми обговоримо всі ці доповнення до інтерфейсів у Java 8, а також обговоримо деякі відмінності між різними поняттями Java, такі як абстрактні класи, ключове слово extends тощо з інтерфейсами.
Статичний метод в інтерфейсі на Java
Інтерфейси також можуть мати методи, які можуть мати визначення. Це статичні методи в інтерфейсі. Статичні методи визначені всередині інтерфейсу, і їх неможливо замінити або змінити класами, що реалізують цей інтерфейс.
Ми можемо викликати ці статичні методи, безпосередньо використовуючи ім'я інтерфейсу.
Наступний приклад демонструє використання статичного методу.
//interface declaration interface TestInterface { // static method definition static void static_print() { System.out.println('TestInterface::static_print ()'); } // abstract method declaration void nonStaticMethod(String str); } // Interface implementation class TestClass implements TestInterface { // Override interface method @Override public void nonStaticMethod(String str) { System.out.println(str); } } public class Main{ public static void main(String() args) { TestClass classDemo = new TestClass(); // Call static method from interface TestInterface.static_print(); // Call overridden method using class object classDemo.nonStaticMethod('TestClass::nonStaticMethod ()'); } }
Вихід:
Вища програма має TestInterface. Він має статичний метод з назвою 'static_print', а також нестатичний метод з назвою nonstaticmethod.
Ми застосували TestInterface у TestClass і перевизначили nonStaticMethod. Тоді в основному методі ми викликаємо метод static_print безпосередньо за допомогою TestInterface та nonStaticMethod, використовуючи об'єкт TestClass.
Метод інтерфейсу за замовчуванням
Як уже зазначалося, інтерфейси до Java 8 дозволяли лише абстрактні методи. Тоді ми запропонували б реалізацію цього методу в окремому класі. Якщо нам довелося додати новий метод до інтерфейсу, то ми повинні надати його код реалізації в тому ж класі.
Отже, якщо ми змінимо інтерфейс, додавши до нього метод, клас реалізації також зміниться.
Це обмеження було подолано версією Java 8, яка дозволила інтерфейсам мати методи за замовчуванням. Методи за замовчуванням певним чином забезпечують зворотну сумісність із існуючими інтерфейсами, і нам не потрібно змінювати клас реалізації. Методи за замовчуванням також відомі як 'метод віртуального розширення' або 'методи захисника'.
Методи за замовчуванням оголошуються за допомогою ключового слова “за замовчуванням” у декларації. Після декларації йде визначення методу. Ми можемо замінити метод за замовчуванням, оскільки він доступний для класу, який реалізує інтерфейс.
Таким же чином ми можемо викликати його, використовуючи об'єкт класу реалізації безпосередньо з інтерфейсу, не перевизначаючи його.
interface TestInterface { // abstract method public void cubeNumber(int num); // default method default void print() { System.out.println('TestInterface :: Default method'); } } class TestClass implements TestInterface { // override cubeNumber method public void cubeNumber(int num) { System.out.println('Cube of given number ' + num+ ':' + num*num*num); } } class Main{ public static void main(String args()) { TestClass obj = new TestClass(); obj.cubeNumber(5); // call default method print using class object obj.print(); } }
Вихід:
Команди сценаріїв оболонки Unix з прикладами
Наведена вище програма Java демонструє метод інтерфейсу за замовчуванням. В основному методі зауважте, що ми можемо викликати метод інтерфейсу за замовчуванням за допомогою об’єкта класу. Це пояснюється тим, що оскільки клас реалізує інтерфейс, метод за замовчуванням доступний і для класу.
Примітка: Ми могли б замінити метод print () також у класі реалізації. Зверніть увагу, що якщо його замінено, модифікатор доступу методу за замовчуванням зміниться на загальнодоступний у класі реалізації.
Методи за замовчуванням та множинне успадкування
У випадку декількох інтерфейсів може виникнути ситуація, коли кожен інтерфейс може мати метод за замовчуванням з однаковим прототипом. У такому випадку компілятор не знає, який метод використовувати.
Коли виникає така ситуація, коли метод за замовчуванням має однаковий прототип у всіх інтерфейсах, рішення полягає в тому, щоб замінити метод у класі реалізації, щоб, коли об'єкт класу реалізації викликає метод за замовчуванням, компілятор викликав метод, реалізований у класі .
Наступна програма Java демонструє використання методу за замовчуванням із декількома інтерфейсами.
//Interface_One interface Interface_One{ //defaultMethod default void defaultMethod(){ System.out.println('Interface_One::defaultMethod'); } } //Interface_Two interface Interface_Two{ //defaultMethod default void defaultMethod(){ System.out.println('Interface_Two::defaultMethod'); } } class TestExample implements Interface_One, Interface_Two{ public void disp(String str){ System.out.println('String is: '+str); } //override defaultMethod to take care of the ambiguity public void defaultMethod(){ System.out.println('TestExample::defaultMethod'); } } class Main{ public static void main(String() args) { TestExample obj = new TestExample(); //call the default method obj.defaultMethod(); } }
Вихід:
У наведеній вище програмі ми замінили метод за замовчуванням (який має однаковий прототип в обох інтерфейсах) у класі реалізації. Таким чином, коли ми викликаємо метод за замовчуванням з основного методу, використовуючи об’єкт класу реалізації, викликається перевизначений метод.
Функціональні інтерфейси Java 8
Функціональний інтерфейс - це інтерфейс, який має лише один абстрактний метод. Він може містити будь-яку кількість стандартних та статичних методів, але абстрактний метод, який він містить, є точно одним. Крім того, функціональний інтерфейс може мати декларації методів класу об'єктів.
Функціональний інтерфейс відомий як “ Інтерфейс єдиного абстрактного методу ”Або“ Інтерфейс SAM '. Інтерфейс SAM - це нова функція в Java.
У програмі Java наявність функціонального інтерфейсу вказується за допомогою @FunctionalInterface анотація. Коли компілятор зустрічає цю анотацію, він знає, що інтерфейс, який слідує за цією анотацією, є функціональним. Отже, якщо він містить більше одного абстрактного методу, то блимає помилка.
Анотація @FunctionalInterface однак, це не є обов'язковим для Java.
Наступна програма демонструє функціональний інтерфейс у Java:
//declare a functional interface @FunctionalInterface //annotation indicates it’s a functional interface interface function_Interface{ void disp_msg(String msg); // abstract method // Object class methods. int hashCode(); String toString(); boolean equals(Object obj); } //implementation of Functional Interface class FunctionalInterfaceExample implements function_Interface{ public void disp_msg(String msg){ System.out.println(msg); } } class Main{ public static void main(String() args) { //create object of implementation class and call method FunctionalInterfaceExample finte = new FunctionalInterfaceExample(); finte.disp_msg('Hello, World!!!'); } }
Вихід:
Функціональний інтерфейс у наведеній вище програмі має єдиний абстрактний метод, а також має декларацію методу класу об'єкта, як hashCode, toString та equals. У класі, який реалізує цей інтерфейс, абстрактний метод замінено. В основному методі ми створюємо об'єкт класу реалізації та використовуємо метод.
програмний пакет, призначений для автоматизації контролю версій
Інтерфейси, такі як Runnable та Comparable, є прикладами функціональних інтерфейсів, що надаються в Java. Java 8 дозволяє нам призначати лямбда-вирази об'єкту функціонального інтерфейсу.
Наступний приклад програми це демонструє.
class Main{ public static void main(String args()) { // use lambda expression to create the object new Thread(()-> {System.out.println('New thread created with functional interface');}).start(); } }
Вихід:
Java 8 також забезпечує безліч вбудованих функціональних інтерфейсів у пакеті java.util.function.
Ці вбудовані інтерфейси описані нижче:
# 1) Присудок
Це функціональний інтерфейс у Java, який має єдиний тест абстрактних методів. Метод ‘test’ повертає логічне значення після тестування зазначеного аргументу.
Нижче наведено прототип для методу тестування інтерфейсу Predicate.
public interface Predicate { public boolean test(T t); }
# 2) BinaryOperator
Інтерфейс BinaryOperator забезпечує абстрактний метод 'apply', який приймає два аргументи і повертає результуюче значення того самого типу, що і аргументи.
Прототипом методу accept є:
public interface BinaryOperator { public T apply (T x, T y); }
# 3) Функція
Інтерфейс функцій - це функціональний інтерфейс, який також має абстрактний метод із назвою «застосовувати». Однак цей метод застосування бере один аргумент типу T і повертає значення типу R.
Прототип методу застосування такий:
public interface Function { public R apply(T t); }
Наступна програма Java демонструє вищевказаний вбудований предикат функціонального інтерфейсу.
import java.util.*; import java.util.function.Predicate; class Main { public static void main(String args()) { // create a list of strings List names = Arrays.asList('Karen','Mia','Sydney','Lacey','Megan'); // declare string type predicate and use lambda expression to create object Predicate p = (s)->s.startsWith('M'); System.out.println('Names starting with M:'); // Iterate through the list for (String st:names) { // test each entry with predicate if (p.test(st)) System.out.println(st); } } }
Вихід:
Як ми можемо бачити у наведеній вище програмі, у нас є список рядків. Використовуючи функціональний інтерфейс Predicate, ми перевіряємо, чи починається елемент у рядку з M, а якщо так, то друкує ім'я.
Інтерфейс класу проти Java
Хоча клас і інтерфейс схожі, оскільки мають схожий синтаксис, ці дві сутності мають більше відмінностей, ніж подібностей.
Давайте перелічимо деякі відмінності між класом та інтерфейсом у Java.
Клас | Інтерфейс |
---|---|
Ми можемо створювати екземпляри та створювати об’єкти з класу. | Неможливо створити екземпляр інтерфейсу. |
Ключове слово «клас» використовується для створення класу. | Інтерфейс створюється за допомогою ключового слова ‘інтерфейс’. |
Класи не підтримують множинне успадкування в Java. | Інтерфейси підтримують множинне успадкування в Java. |
Клас містить конструктори. | Інтерфейси не містять конструкторів. |
Клас не може містити абстрактних методів. | Інтерфейси містять лише абстрактні методи. |
Клас може мати змінні та методи, які є типовими, загальнодоступними, приватними або захищеними. | Інтерфейс має лише загальнодоступні змінні та методи за замовчуванням. |
Не обов’язково пов’язувати модифікатори, що не мають доступу, зі змінними класу. | Інтерфейси можуть мати статичні або кінцеві змінні. |
Ми можемо успадкувати інший клас від класу. | Ми не можемо успадкувати клас з інтерфейсу. |
Клас можна успадкувати за допомогою ключового слова ‘extends’. | Інтерфейс може бути реалізований іншим класом за допомогою ключового слова ‘implements’. Він може успадковуватися іншим інтерфейсом за допомогою ключового слова „extends”. |
Java розширює реалізації Vs
«Поширюється» | «Знаряддя праці» |
---|---|
Інтерфейси підтримують лише статичні та остаточні модифікатори, що не мають доступу. | Анотація підтримує всі модифікатори, що не мають доступу, такі як статичний, фінальний, нестатичний та нефінальний. |
Клас використовує ключове слово „extends” для успадкування від іншого класу. | Ключове слово ‘implements’ використовується класом для реалізації інтерфейсу. |
Клас, що успадковує інший клас, може замінити чи не замінити всі методи батьківського класу. | Клас, що реалізує інтерфейс, повинен замінити всі абстрактні методи інтерфейсу. |
Одночасно ми можемо розширити лише один клас, використовуючи ключове слово extends. | Ми можемо реалізувати кілька інтерфейсів, використовуючи ключове слово ‘implements’. |
Інтерфейс може розширити інший інтерфейс за допомогою ключового слова „extends”. | Інтерфейс не може реалізовувати інший інтерфейс, використовуючи ключові слова „implements“. |
Може абстрактний клас реалізувати інтерфейс в Java
Так, абстрактний клас може реалізувати інтерфейс за допомогою ключового слова ‘implements’. Абстрактний клас не повинен реалізовувати всі абстрактні методи інтерфейсу. Але загалом хорошою практикою дизайну є наявність інтерфейсу з усіма абстрактними методами, потім абстрактний клас, що реалізує цей інтерфейс, а потім конкретні класи.
Нижче наведено приклад такої реалізації в Java.
Тут java.util.List - це інтерфейс. Цей інтерфейс реалізований java.util.AbstractList. Потім цей клас AbstractList розширюється двома конкретними класами, тобто LinkedList та ArrayList.
Якби класи LinkedList та ArrayList реалізовували інтерфейс List безпосередньо, тоді їм довелося б реалізувати всі абстрактні методи інтерфейсу List.
Але в цьому випадку клас AbstractList реалізує методи інтерфейсу List та передає їх LinkedList та ArrayList. Отже, тут ми отримуємо перевагу оголошення типу з інтерфейсу та гнучкість абстрактного класу реалізації загальної поведінки.
Коли використовувати абстрактний клас та інтерфейс у Java
В основному ми використовуємо абстрактний клас, щоб визначити типову або типову поведінку дочірніх класів, які поширюватимуться на цей абстрактний клас. Інтерфейс використовується для визначення контракту між двома системами, які взаємодіють у додатку.
Певні конкретні ситуації ідеально підходять для використання інтерфейсів та певних проблем, які можна вирішити лише за допомогою абстрактних класів. У цьому розділі ми обговоримо, коли ми можемо використовувати інтерфейс і коли ми можемо використовувати абстрактні класи.
Коли використовувати інтерфейс:
- Інтерфейси в основному використовуються, коли у нас є невелика стисла функціональність для реалізації.
- Коли ми впроваджуємо API і знаємо, що вони певний час не зміняться, тоді ми використовуємо інтерфейси.
- Інтерфейси дозволяють нам реалізувати множинне успадкування. Отже, коли нам потрібно реалізувати множинне успадкування в нашому додатку, ми використовуємо інтерфейси.
- Коли ми маємо широкий спектр об’єктів, знову ж таки інтерфейси є кращим вибором.
- Крім того, коли нам доводиться надавати загальну функціональність багатьом непов’язаним класам, все ще використовуються інтерфейси.
Коли використовувати абстрактний клас:
- Абстрактні класи в основному використовуються, коли нам потрібно використовувати успадкування в нашому додатку.
- Оскільки інтерфейси мають справу із загальнодоступними методами та змінними, щоразу, коли ми хочемо використовувати непублічні модифікатори доступу в нашій програмі, ми використовуємо абстрактні класи.
- Якщо потрібно додати нові методи, то краще це робити в абстрактному класі, ніж в інтерфейсі. Оскільки, якщо ми додаємо новий метод в інтерфейс, вся реалізація змінюється, оскільки інтерфейси мають лише прототипи методів, а реалізація класу за допомогою інтерфейсу забезпечить реалізацію.
- Якщо ми хочемо, щоб розроблялись різні версії компонентів, тоді ми йдемо на абстрактний клас. Ми можемо легше змінювати абстрактні класи. Але інтерфейси змінити не можна. Якщо ми хочемо нову версію, то нам доведеться написати весь інтерфейс знову.
- Коли ми хочемо надати загальну реалізацію для всіх компонентів, тоді абстрактний клас є найкращим вибором.
Інтерфейс проти абстрактного класу в Java
Нижче наведено деякі відмінності між класами Interfaces та Abstract у Java.
Інтерфейс | Абстрактний клас |
---|---|
Інтерфейс оголошується за допомогою ключового слова „інтерфейс”. | Абстрактний клас оголошується за допомогою ключового слова ‘abstract’. |
Інтерфейс може бути реалізований за допомогою ключового слова ‘implements’. | Анотація може бути успадкована за допомогою ключового слова „extends”. |
Інтерфейс не може розширити клас або реалізувати інтерфейс, він може лише розширити інший інтерфейс. | Абстрактний клас може розширити клас або реалізувати кілька інтерфейсів. |
Члени інтерфейсу можуть бути лише загальнодоступними. | Учасники абстрактних класів можуть бути публічними, приватними або захищеними. |
Інтерфейс не може бути використаний для забезпечення реалізації. Його можна використовувати лише як декларацію. | Для реалізації інтерфейсу можна використовувати абстрактний клас. |
Багаторазове успадкування можна досягти за допомогою інтерфейсів. | Абстрактний клас не підтримує множинне успадкування. |
Інтерфейси можуть мати лише абстрактні методи. З Java 8 він може мати статичні методи та методи за замовчуванням. | Абстрактний клас може мати абстрактний або не абстрактний метод. |
Спадщина Enum у Java
Ми обговорили типи даних enum у нашому обговоренні типів даних у Java. Усі переліки поширюються від класу java.lang.Enum. Цей клас java.lang.Enum є абстрактним класом.
Крім того, усі класи перерахування в Java за замовчуванням є 'кінцевими'. Отже, спроба успадкувати клас з будь-яких класів перерахування призводить до помилки компілятора.
Оскільки Java не дозволяє багаторазове успадкування, ми не можемо успадкувати клас enum від будь-якого іншого класу, оскільки клас enum вже успадковується від java.lang.Enum. Однак класи enum можуть реалізовувати інтерфейси на Java, і це називається успадкуванням Enum у Java.
Нижче наведено приклад успадкування Enum у Java.
//WeekDays interface declaration interface WeekDays { public void displaydays(); } //enum class implementing WeekDays interface enum Days implements WeekDays { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY,FRIDAY, SATURDAY; public void displaydays() { //Override displaydays method System.out.println('The day of the week: ' + this); } } class Main { public static void main(String() args) { Days.MONDAY.displaydays(); //access enum value } }
Вихід:
Тут ми маємо інтерфейс WeekDays з абстрактним методом prototype displaydays (). Потім ми визначаємо клас enum Days, який реалізує інтерфейс WeekDays. Тут ми визначаємо значення переліку від НЕДЕЛІ до СУБОТИ, а також замінюємо метод displaydays.
Нарешті, в основному методі ми отримуємо доступ до значення переліку та відображаємо його.
Часті запитання
Q # 1) Що станеться, якщо ви вкажете тіло методу в інтерфейсі?
Відповідь: Для версій Java до Java 8 тіло методу заборонено в інтерфейсі. Але оскільки Java 8, ми можемо визначити за замовчуванням або статичні методи всередині інтерфейсу.
Q # 2) Чи може інтерфейс мати змінні в Java 8?
Відповідь: Ми можемо мати постійні змінні в Java 8, використовуючи статичні та остаточні модифікатори. Але ми не можемо мати змінних екземплярів в інтерфейсах Java. Будь-яка спроба оголосити змінні екземпляра в інтерфейсі призведе до помилки компілятора.
Запитання №3) Які вдосконалення мають інтерфейси в Java 8?
Відповідь: Найважливішим вдосконаленням інтерфейсів у Java 8 є те, що в інтерфейсах дозволено статичні та стандартні методи. Ми можемо мати методи, оголошені як статичні або за замовчуванням, і визначати їх всередині інтерфейсу.
Q # 4) Чи можемо ми замінити метод за замовчуванням в інтерфейсі Java?
Відповідь: Ні. Не обов’язково замінювати метод інтерфейсу за замовчуванням. Це тому, що коли ми реалізуємо інтерфейс у класі, тоді метод класу за замовчуванням доступний для класу реалізації. Отже, використовуючи об'єкт класу реалізації, ми можемо отримати доступ до методу інтерфейсу за замовчуванням.
Q # 5) Чи можуть інтерфейси мати поля в Java?
які програми використовують c ++
Відповідь: Так, ми можемо мати поля або змінні в інтерфейсах на Java, але за замовчуванням всі ці поля є статичними, кінцевими та загальнодоступними.
Висновок
У цьому підручнику ми обговорили зміни, внесені в інтерфейси в Java 8. Java 8 представила статичні методи та методи за замовчуванням в інтерфейсах. Раніше в інтерфейсі ми могли мати лише абстрактні методи. Але починаючи з Java 8, ми можемо визначати стандартні та статичні методи в Java.
Крім того, Java 8 дозволяє використовувати лямбда-вирази з функціональними інтерфейсами в Java. Потім ми також обговорили абстрактні класи та інтерфейси та побачили, коли використовувати кожен із них у Java. Ми також бачили успадкування переліку в Java.
Ми також обговорили деякі відмінності між розширеннями та реалізаціями, класом та інтерфейсом, абстрактним класом та інтерфейсом тощо.
=> Перевірте ВСІ підручники Java тут.
Рекомендована література
- Інтерфейс Java та підручник з абстрактних класів із прикладами
- Порівнянні та порівняльні інтерфейси в Java
- Інтерфейс ListIterator в Java з прикладами
- Встановити інтерфейс у Java: Підручник із набору Java з прикладами
- Інтерфейс маркера в Java: серіалізується та клонується
- Довжина рядка Java () Метод із прикладами
- Розгортання Java: Створення та виконання файлу JAR Java
- Як використовувати метод Java toString?