interface enhancements java 8 java functional interface
Този урок обяснява допълненията към интерфейса в Java 8 и разликите между Java понятия като абстрактен клас, разширява ключова дума и т.н. с интерфейсите:
Проучихме всичко Интерфейси в Java в последния ни урок. Въведохме и обхванахме основните понятия за интерфейси в Java, включително множество интерфейси.
Преди Java 8 на интерфейсите беше разрешено да имат само абстрактни методи и статични и крайни променливи. Абстрактните методи по подразбиране са публични и трябва да бъдат заменени от класа, който реализира интерфейс.
Така че интерфейсът беше предимно договор и беше ангажиран само с константи (статични и окончателни) и абстрактни методи.
=> Погледнете тук ръководството за начинаещи Java.
Какво ще научите:
- Промени в интерфейсите в Java 8
- Функционални интерфейси Java 8
- Интерфейс от клас Vs в Java
- Java разширява Vs Implements
- Интерфейс срещу абстрактния клас в 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(); } }
Изход:
имам нужда от фалшив имейл адрес
Горната програма Java демонстрира метода по подразбиране в интерфейса. В основния метод имайте предвид, че можем да извикаме метода по подразбиране на интерфейса, използвайки обекта на класа. Това е така, тъй като класът изпълнява интерфейса, методът по подразбиране е достъпен и за класа.
Забележка: Можехме да заменим метода print () и в класа на внедряване. Имайте предвид, че ако бъде заменено, тогава модификаторът на достъп на метода по подразбиране ще се промени на обществен в класа на изпълнение.
Методи по подразбиране и множествено наследяване
Може да възникне ситуация в случай на множество интерфейси, при които всеки интерфейс може да има метод по подразбиране със същия прототип. В такъв случай компилаторът не знае кой метод да извика.
Когато възникне тази ситуация, при която методът по подразбиране има един и същ прототип във всички интерфейси, тогава решението е да се замени методът в класа на изпълнение, така че когато обектът на класа на изпълнение извиква метода по подразбиране, компилаторът извиква метода, реализиран в класа .
е unix и linux същото
Следващата програма 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) Функция
Функционалният интерфейс е функционален интерфейс, който също има абстрактен метод, наречен „apply“. Този метод на прилагане обаче взема един аргумент от тип 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 и ако го направи, той отпечатва името.
Интерфейс от клас Vs в Java
Въпреки че класът и интерфейсът са сходни, тъй като имат сходен синтаксис, тези две обекти имат повече разлики, отколкото прилики.
Нека изброим някои от разликите между класа и интерфейса в Java.
Клас | Интерфейс |
---|---|
Можем да създаваме екземпляри и да създаваме обекти от клас. | Интерфейс не може да бъде създаден. |
Ключовата дума „клас“ се използва за създаване на клас. | Интерфейсът се създава с помощта на ключовата дума „интерфейс“. |
Класовете не поддържат множествено наследяване в Java. | Интерфейсите поддържат множествено наследяване в Java. |
Класът съдържа конструкторите. | Интерфейсите не съдържат конструктори. |
Класът не може да съдържа абстрактни методи. | Интерфейсите съдържат само абстрактни методи. |
Класът може да има променливи и методи, които са по подразбиране, публични, частни или защитени. | Интерфейсът има само публични променливи и методи по подразбиране. |
Не е задължително да се свързват модификатори за недостъп с променливи от класа. | Интерфейсите могат да имат променливи, които са или статични, или окончателни. |
Можем да наследим друг клас от клас. | Не можем да наследим клас от интерфейса. |
Класът може да бъде наследен с помощта на ключовата дума ‘extends’. | Интерфейсът може да бъде реализиран от друг клас, използвайки ключовата дума ‘implements’. Тя може да бъде наследена от друг интерфейс, използвайки ключова дума „extends“. |
Java разширява Vs Implements
‘Удължава’ | ‘Приспособления’ |
---|---|
Интерфейсите поддържат само статични и крайни модификатори без достъп. | Абстрактът поддържа всички модификатори без достъп като статични, окончателни, нестатични и не-окончателни. |
Клас използва ключова дума „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
По-долу са дадени някои от разликите между интерфейсите и абстрактните класове в Java.
Интерфейс | Абстрактен клас |
---|---|
Интерфейсът се декларира с помощта на ключовата дума ‘interface’. | Абстрактният клас се декларира с помощта на ключовата дума ‘abstract’. |
Интерфейсът може да бъде реализиран с помощта на ключовата дума ‘implements’. | Резюмето може да бъде наследено с помощта на ключова дума „extends“. |
Интерфейсът не може да разшири клас или да приложи интерфейс, той може да разшири само друг интерфейс. | Абстрактният клас може да разшири клас или да реализира множество интерфейси. |
Членовете на интерфейса могат да бъдат публични. | Членовете на абстрактния клас могат да бъдат публични, частни или защитени. |
Интерфейс не може да се използва за осигуряване на изпълнение. Може да се използва само като декларация. | За реализиране на интерфейса може да се използва абстрактен клас. |
Многократно наследяване може да се постигне с помощта на интерфейси. | Абстрактният клас не поддържа множествено наследяване. |
Интерфейсите могат да имат само абстрактни методи. От Java 8 той може да има статични и стандартни методи. | Абстрактен клас може да има абстрактен или не-абстрактен метод. |
Наследяване на Enum в Java
Обсъдихме типовете данни на enum в нашата дискусия за типовете данни в Java. Всички изброявания се простират от клас java.lang.Enum. Този клас java.lang.Enum е абстрактен клас.
Също така, всички 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 с абстрактен метод прототип displaydays (). След това дефинираме enum клас Days, който реализира интерфейса WeekDays. Тук дефинираме стойностите на изброяването от НЕДЕЛЯ до СЪБОТА и също така заменяме метода displaydays.
И накрая, в основния метод имаме достъп до стойността на изброяването и я показваме.
често задавани въпроси
В # 1) Какво се случва, ако дадете тяло на метода в интерфейса?
Отговор: За версии на Java преди Java 8, тялото на метода не е разрешено в интерфейса. Но тъй като Java 8, можем да дефинираме по подразбиране или статични методи в интерфейса.
В # 2) Може ли интерфейсът да има променливи в Java 8?
Отговор: Можем да имаме постоянни променливи в Java 8, използвайки статични и окончателни модификатори. Но не можем да имаме променливи на екземпляра в интерфейсите на Java. Всеки опит за деклариране на променливи на екземпляра в интерфейс ще доведе до грешка в компилатора.
В # 3) Какви са подобренията в интерфейсите в Java 8?
Отговор: Най-важното подобрение за интерфейсите в Java 8 е, че в интерфейсите са разрешени статични и методи по подразбиране. Можем да имаме методи, декларирани като статични или по подразбиране, и да ги дефинираме вътре в интерфейса.
В # 4) Можем ли да заменим метода по подразбиране в интерфейса на Java?
Отговор: Не. Не е задължително да се заменя метода по подразбиране в интерфейса. Това е така, защото когато внедряваме интерфейс в клас, тогава методът по подразбиране на класа е достъпен за класа на внедряване. Следователно, използвайки обекта на класа на внедряване, можем да получим достъп до метода по подразбиране на интерфейса.
В # 5) Може ли интерфейсите да имат полета в Java?
какви програми използват c ++
Отговор: Да, можем да имаме полета или променливи в интерфейсите в Java, но по подразбиране всички тези полета са статични, окончателни и публични.
Заключение
В този урок обсъдихме промените, направени в интерфейсите в Java 8. Java 8 въведе статични и стандартни методи в интерфейсите. По-рано можехме да имаме само абстрактни методи в интерфейса. Но от Java 8 нататък можем да дефинираме по подразбиране и статични методи в Java.
Също така Java 8 позволява използването на ламбда изрази с функционалните интерфейси в Java. След това обсъдихме и абстрактни класове и интерфейси и видяхме кога да използваме всеки от тях в Java. Виждали сме и наследяването на enum в Java.
Също така обсъдихме някои от разликите между разширенията и изпълненията, клас и интерфейс, абстрактен клас и интерфейс и т.н.
=> Проверете ВСИЧКИ уроци за Java тук.
Препоръчително четене
- Урок за интерфейс на Java и абстрактен клас с примери
- Сравними и сравнителни интерфейси в Java
- ListIterator интерфейс в Java с примери
- Задаване на интерфейс в Java: Урок за задаване на Java с примери
- Интерфейс на маркер в Java: Сериализуем и клонируем
- Дължина на низа на Java () Метод с примери
- Разполагане на Java: Създаване и изпълнение на Java JAR файл
- Как да използвам Java toString метод?