interface enhancements java 8 java functional interface
W tym samouczku wyjaśniono dodatki do interfejsu w Javie 8 i różnice między pojęciami Java, takimi jak klasa abstrakcyjna, słowo kluczowe extends itp. Z interfejsami:
Zbadaliśmy wszystko Interfejsy w Javie w naszym ostatnim samouczku. Przedstawiliśmy i omówiliśmy podstawowe koncepcje dotyczące interfejsów w Javie, w tym wiele interfejsów.
Przed Java 8 interfejsy mogły mieć tylko abstrakcyjne metody oraz zmienne statyczne i końcowe. Metody abstrakcyjne są domyślnie publiczne i muszą zostać przesłonięte przez klasę implementującą interfejs.
Zatem interfejs był głównie kontraktem i był związany tylko ze stałymi (statycznymi i końcowymi) oraz metodami abstrakcyjnymi.
=> Zapoznaj się z podręcznikiem Java dla początkujących tutaj.
Czego się nauczysz:
- Zmiany interfejsów w Javie 8
- Interfejsy funkcjonalne Java 8
- Interfejs klasy Vs w Javie
- Java Extends Vs Implements
- Interfejs Vs Klasa abstrakcyjna w Javie
- Wniosek
Zmiany interfejsów w Javie 8
Wydanie Java 8 wprowadza lub pozwala nam mieć statyczne i domyślne metody w interfejsach. Korzystając z metod domyślnych w interfejsie, programiści mogą dodać więcej metod do interfejsów. W ten sposób nie zakłócają ani nie zmieniają klas implementujących interfejs.
Java 8 umożliwia również interfejsowi posiadanie metody statycznej. Metody statyczne są takie same, jak te, które definiujemy w klasach. Należy zauważyć, że metoda statyczna nie może zostać zastąpiona przez klasę implementującą interfejs.
Wprowadzenie statycznych i domyślnych metod w interfejsie ułatwiło bezproblemową zmianę interfejsów, a także ułatwiło implementację interfejsów.
Java 8 wprowadza również „Wyrażenia lambda” do interfejsów funkcjonalnych. Poza tym, począwszy od Java 8, w Javie dodano więcej wbudowanych interfejsów funkcjonalnych.
W tym samouczku omówimy wszystkie dodatki do interfejsów w Javie 8, a także omówimy niektóre różnice między różnymi koncepcjami języka Java, takimi jak klasy abstrakcyjne, słowo kluczowe extends itp. Z interfejsami.
Metoda statyczna w interfejsie w Javie
Interfejsy mogą również mieć metody, które mogą mieć definicje. To są statyczne metody interfejsu. Metody statyczne są zdefiniowane w interfejsie i nie mogą być zastępowane ani zmieniane przez klasy implementujące ten interfejs.
Możemy wywołać te statyczne metody, używając bezpośrednio nazwy interfejsu.
Poniższy przykład demonstruje użycie metody statycznej.
//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 ()'); } }
Wynik:
Powyższy program ma interfejs TestInterface. Ma statyczną metodę o nazwie „static_print”, a także metodę niestatyczną o nazwie nonstaticmethod.
Zaimplementowaliśmy TestInterface w TestClass i nadpisaliśmy nonStaticMethod. Następnie w metodzie main wywołujemy metodę static_print bezpośrednio przy użyciu TestInterface i nonStaticMethod przy użyciu obiektu TestClass.
Domyślna metoda interfejsu
Jak już wspomniano, interfejsy przed Java 8 dopuszczały tylko metody abstrakcyjne. Następnie zapewnilibyśmy implementację tej metody w osobnej klasie. Gdybyśmy musieli dodać nową metodę do interfejsu, to musimy dostarczyć jej kod implementacyjny w tej samej klasie.
Dlatego gdybyśmy zmienili interfejs, dodając do niego metodę, klasa implementacji również by się zmieniła.
To ograniczenie zostało pokonane przez wersję Java 8, która pozwoliła interfejsom na używanie domyślnych metod. Metody domyślne w pewien sposób zapewniają wsteczną kompatybilność z istniejącymi interfejsami i nie musimy zmieniać klasy implementacji. Metody domyślne są również znane jako „metoda wirtualnego rozszerzenia” lub „metody obrońcy”.
Metody domyślne są deklarowane przy użyciu słowa kluczowego „default” w deklaracji. Po deklaracji następuje definicja metody. Możemy przesłonić domyślną metodę, ponieważ jest ona dostępna dla klasy implementującej interfejs.
W ten sam sposób możemy go wywołać przy użyciu obiektu klasy implementacji bezpośrednio z interfejsu, bez nadpisywania.
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(); } }
Wynik:
gdzie znajdę klucz sieciowy
Powyższy program Java demonstruje domyślną metodę w interfejsie. W metodzie main zwróć uwagę, że domyślną metodę interfejsu możemy wywołać za pomocą obiektu klasy. Dzieje się tak, ponieważ ponieważ klasa implementuje interfejs, domyślna metoda jest również dostępna dla tej klasy.
Uwaga: Mogliśmy przesłonić metodę print () również w klasie implementacji. Należy zauważyć, że w przypadku zastąpienia modyfikator dostępu metody domyślnej zmieni się na public w klasie implementacji.
Metody domyślne i wielokrotne dziedziczenie
W przypadku wielu interfejsów może wystąpić sytuacja, w której każdy interfejs może mieć domyślną metodę z tym samym prototypem. W takim przypadku kompilator nie wie, którą metodę wywołać.
Gdy zaistnieje taka sytuacja, w której metoda domyślna ma ten sam prototyp we wszystkich interfejsach, wówczas rozwiązaniem jest przesłonięcie metody w klasie implementacji tak, aby w momencie wywołania metody domyślnej przez obiekt klasy implementacji kompilator wywoływał metodę zaimplementowaną w klasie .
Poniższy program w języku Java demonstruje użycie metody domyślnej z wieloma interfejsami.
najlepszy monitor temperatury procesora i procesora graficznego
//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(); } }
Wynik:
W powyższym programie nadpisaliśmy domyślną metodę (która ma ten sam prototyp w obu interfejsach) w klasie implementacji. W ten sposób, gdy wywołujemy metodę domyślną z metody głównej przy użyciu obiektu klasy implementacji, wywoływana jest metoda przesłonięta.
Interfejsy funkcjonalne Java 8
Interfejs funkcjonalny to interfejs, który ma tylko jedną abstrakcyjną metodę. Może zawierać dowolną liczbę metod domyślnych i statycznych, ale metoda abstrakcyjna, którą zawiera, to dokładnie jedna. Dodatkowo interfejs funkcjonalny może mieć deklaracje metod klas obiektów.
Interfejs funkcjonalny jest znany jako „ Pojedynczy interfejs metody abstrakcyjnej ”Lub„ Interfejs SAM ”. Interfejs SAM to nowa funkcja w Javie.
W programie Java obecność funkcjonalnego interfejsu jest wskazywana za pomocą @FunctionalInterface adnotacja. Kiedy kompilator napotka tę adnotację, wie, że interfejs, który podąża za tą adnotacją, działa. Stąd, jeśli zawiera więcej niż jedną metodę abstrakcyjną, miga błąd.
Adnotacja @FunctionalInterface jednak nie jest obowiązkowe w Javie.
Poniższy program demonstruje interfejs funkcjonalny w Javie:
//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!!!'); } }
Wynik:
Interfejs funkcjonalny w powyższym programie ma jedną abstrakcyjną metodę, a także ma deklarację metody klasy obiektu, taką jak hashCode, toString i equals. W klasie implementującej ten interfejs nadpisywana jest metoda abstrakcyjna. W metodzie głównej tworzymy obiekt klasy implementacyjnej i używamy metody.
Interfejsy takie jak Runnable i Comparable to przykłady funkcjonalnych interfejsów udostępnionych w Javie. Java 8 pozwala nam przypisywać wyrażenia lambda do obiektu interfejsu funkcjonalnego.
Poniższy przykładowy program demonstruje to.
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(); } }
Wynik:
Java 8 zapewnia również wiele wbudowanych interfejsów funkcjonalnych w pakiecie java.util.function.
Te wbudowane interfejsy opisano poniżej:
# 1) Orzeczenie
To jest funkcjonalny interfejs w Javie, który ma pojedynczy test metody abstrakcyjnej. Metoda „test” zwraca wartość logiczną po przetestowaniu określonego argumentu.
Poniżej podano prototyp metody testowej interfejsu Predicate.
public interface Predicate { public boolean test(T t); }
# 2) BinaryOperator
Interfejs BinaryOperator udostępnia abstrakcyjną metodę „zastosuj”, która przyjmuje dwa argumenty i zwraca wynikową wartość tego samego typu co argumenty.
Prototyp metody accept to:
public interface BinaryOperator { public T apply (T x, T y); }
# 3) Funkcja
Interfejs funkcji to interfejs funkcjonalny, który ma również abstrakcyjną metodę o nazwie „zastosuj”. Ta metoda Apply przyjmuje jednak pojedynczy argument typu T i zwraca wartość typu R.
Prototyp metody zastosuj jest następujący:
public interface Function { public R apply(T t); }
Poniższy program w języku Java demonstruje powyższy wbudowany predykat interfejsu funkcjonalnego.
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); } } }
Wynik:
Jak widać w powyższym programie mamy listę ciągów. Korzystając z interfejsu funkcjonalnego Predicate, sprawdzamy, czy pozycja w ciągu znaków zaczyna się od M, a jeśli tak, to wypisuje nazwę.
Interfejs klasy Vs w Javie
Chociaż klasa i interfejs są podobne, ponieważ mają podobną składnię, te dwie jednostki mają więcej różnic niż podobieństw.
Wymieńmy niektóre różnice między klasą a interfejsem w Javie.
Klasa | Berło |
---|---|
Możemy tworzyć instancje i tworzyć obiekty z klasy. | Nie można utworzyć wystąpienia interfejsu. |
Do utworzenia klasy służy słowo kluczowe „klasa”. | Interfejs jest tworzony za pomocą słowa kluczowego „interfejs”. |
Klasy nie obsługują dziedziczenia wielokrotnego w Javie. | Interfejsy obsługują wielokrotne dziedziczenie w Javie. |
Klasa zawiera konstruktory. | Interfejsy nie zawierają konstruktorów. |
Klasa nie może zawierać metod abstrakcyjnych. | Interfejsy zawierają tylko abstrakcyjne metody. |
Klasa może mieć zmienne i metody, które są domyślne, publiczne, prywatne lub chronione. | Interfejs ma domyślnie tylko publiczne zmienne i metody. |
Kojarzenie modyfikatorów braku dostępu ze zmiennymi klasy nie jest obowiązkowe. | Interfejsy mogą mieć zmienne, które są statyczne lub ostateczne. |
Możemy odziedziczyć inną klasę z klasy. | Nie możemy dziedziczyć klasy z interfejsu. |
Klasę można dziedziczyć za pomocą słowa kluczowego „extends”. | Interfejs można zaimplementować w innej klasie, używając słowa kluczowego „implements”. Może zostać odziedziczony przez inny interfejs za pomocą słowa kluczowego „extends”. |
Java Extends Vs Implements
„Rozszerza” | 'przybory' |
---|---|
Interfejsy obsługują tylko statyczne i końcowe modyfikatory bez dostępu. | Klasa abstrakcyjna obsługuje wszystkie modyfikatory bez dostępu, takie jak statyczne, końcowe, niestatyczne i nie ostateczne. |
Klasa używa słowa kluczowego „extends”, aby dziedziczyć z innej klasy. | Słowo kluczowe „implements” jest używane przez klasę do implementacji interfejsu. |
Klasa dziedzicząca inną klasę może, ale nie musi, przesłonić wszystkie metody klasy nadrzędnej. | Klasa implementująca interfejs musi przesłonić wszystkie abstrakcyjne metody interfejsu. |
Za pomocą słowa kluczowego extends możemy rozszerzyć tylko jedną klasę naraz. | Możemy zaimplementować wiele interfejsów za pomocą słowa kluczowego „implements”. |
Interfejs może rozszerzyć inny interfejs za pomocą słowa kluczowego „extends”. | Interfejs nie może implementować innego interfejsu za pomocą słów kluczowych „implements”. |
Czy abstrakcyjna klasa może zaimplementować interfejs w języku Java
Tak, klasa abstrakcyjna może implementować interfejs przy użyciu słowa kluczowego „implements”. Klasa abstrakcyjna nie musi implementować wszystkich metod abstrakcyjnych interfejsu. Ogólnie rzecz biorąc, dobrą praktyką projektową jest posiadanie interfejsu ze wszystkimi metodami abstrakcyjnymi, następnie klasą abstrakcyjną implementującą ten interfejs, a następnie klasami konkretnymi.
Poniżej podano przykład takiej implementacji w Javie.
Tutaj java.util.List jest interfejsem. Interfejs ten jest implementowany przez java.util.AbstractList. Następnie ta klasa AbstractList jest rozszerzana o dwie konkretne klasy, tj. LinkedList i ArrayList.
Gdyby klasy LinkedList i ArrayList bezpośrednio implementowały interfejs List, musiałyby zaimplementować wszystkie abstrakcyjne metody interfejsu List.
Ale w tym przypadku klasa AbstractList implementuje metody interfejsu List i przekazuje je do LinkedList i ArrayList. Więc tutaj mamy zaletę deklarowania typu z interfejsu i elastyczności klas abstrakcyjnych implementacji typowego zachowania.
Kiedy używać klasy abstrakcyjnej i interfejsu w Javie
Używamy głównie klasy abstrakcyjnej do definiowania domyślnego lub typowego zachowania klas potomnych, które będą stanowić rozszerzenie tej klasy abstrakcyjnej. Interfejs służy do definiowania kontraktu między dwoma systemami, które współdziałają w aplikacji.
Pewne specyficzne sytuacje są idealne dla używanych interfejsów i pewnych problemów, które można rozwiązać tylko za pomocą klas abstrakcyjnych. W tej sekcji omówimy, kiedy możemy używać interfejsu, a kiedy klas abstrakcyjnych.
Kiedy używać interfejsu:
- Interfejsy są używane głównie wtedy, gdy mamy małą zwięzłą funkcjonalność do zaimplementowania.
- Kiedy wdrażamy interfejsy API i wiemy, że przez jakiś czas się one nie zmienią, wtedy przechodzimy do interfejsów.
- Interfejsy pozwalają nam na implementację wielokrotnego dziedziczenia. Dlatego gdy musimy zaimplementować w naszej aplikacji wielokrotne dziedziczenie, sięgamy po interfejsy.
- Kiedy mamy szeroką gamę obiektów, znowu lepszym wyborem są interfejsy.
- Również wtedy, gdy musimy zapewnić wspólną funkcjonalność wielu niepowiązanym klasom, nadal używane są interfejsy.
Kiedy używać klasy abstrakcyjnej:
- Klasy abstrakcyjne są używane głównie wtedy, gdy w naszej aplikacji musimy skorzystać z dziedziczenia.
- Ponieważ interfejsy obsługują publiczne metody i zmienne, ilekroć chcemy użyć niepublicznych modyfikatorów dostępu w naszym programie, używamy klas abstrakcyjnych.
- Jeśli trzeba dodać nowe metody, lepiej zrobić to w klasie abstrakcyjnej niż w interfejsie. Ponieważ jeśli dodamy nową metodę w interfejsie, cała implementacja się zmieni, ponieważ interfejsy mają tylko prototypy metod, a implementacja klasy za pomocą interfejsu zapewni implementację.
- Jeśli zależy nam na różnych wersjach tworzonych komponentów, wybieramy klasę abstrakcyjną. Możemy łatwiej zmieniać klasy abstrakcyjne. Ale interfejsów nie można zmienić. Jeśli chcemy nową wersję, musimy ponownie napisać cały interfejs.
- Jeśli chcemy zapewnić wspólną implementację dla wszystkich komponentów, najlepszym wyborem jest klasa abstrakcyjna.
Interfejs Vs Klasa abstrakcyjna w Javie
Poniżej podano niektóre różnice między interfejsami a klasami abstrakcyjnymi w Javie.
Berło | Klasa abstrakcyjna |
---|---|
Interfejs jest deklarowany przy użyciu słowa kluczowego „interface”. | Klasa abstrakcyjna jest deklarowana przy użyciu słowa kluczowego „abstract”. |
Interfejs można zaimplementować za pomocą słowa kluczowego „implements”. | Streszczenie można odziedziczyć za pomocą słowa kluczowego „extends”. |
Interfejs nie może rozszerzać klasy ani implementować interfejsu, może jedynie rozszerzać inny interfejs. | Klasa abstrakcyjna może rozszerzać klasę lub implementować wiele interfejsów. |
Członkowie interfejsu mogą być tylko publicznymi. | Członkowie klasy abstrakcyjnej mogą być publicznymi, prywatnymi lub chronionymi. |
Nie można użyć interfejsu do zapewnienia implementacji. Może być używany tylko jako deklaracja. | Do implementacji interfejsu można użyć klasy abstrakcyjnej. |
Za pomocą interfejsów można uzyskać wielokrotne dziedziczenie. | Klasa abstrakcyjna nie obsługuje dziedziczenia wielokrotnego. |
Interfejsy mogą mieć tylko metody abstrakcyjne. Od wersji Java 8 może mieć metody statyczne i domyślne. | Klasa abstrakcyjna może mieć metodę abstrakcyjną lub nieabstrakcyjną. |
Dziedziczenie wyliczeń w Javie
Omówiliśmy enum typy danych w naszej dyskusji na temat typów danych w Javie. Wszystkie wyliczenia pochodzą z klasy java.lang.Enum. Ta klasa java.lang.Enum jest klasą abstrakcyjną.
Ponadto wszystkie klasy wyliczeniowe w Javie są domyślnie „ostateczne”. W związku z tym próba dziedziczenia klasy z dowolnej klasy wyliczeniowej skutkuje błędem kompilatora.
Ponieważ Java nie zezwala na wielokrotne dziedziczenie, nie możemy dziedziczyć klasy wyliczeniowej z żadnej innej klasy, ponieważ klasa wyliczeniowa dziedziczy już po java.lang.Enum. Jednak klasy wyliczeniowe mogą implementować interfejsy w Javie, co w Javie nazywa się dziedziczeniem enum.
Poniżej podano przykład dziedziczenia wyliczeń w Javie.
//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 } }
Wynik:
Tutaj mamy interfejs WeekDays z abstrakcyjnym prototypem metody displaydays (). Następnie definiujemy klasę wyliczeniową Days, która implementuje interfejs WeekDays. Tutaj definiujemy wartości wyliczenia od niedziela do soboty, a także zastępujemy metodę displaydays.
Na koniec w metodzie main uzyskujemy dostęp do wartości wyliczenia i wyświetlamy ją.
Często Zadawane Pytania
Pytanie 1) Co się stanie, jeśli w interfejsie podasz treść metody?
Odpowiedź: W przypadku wersji Java starszych niż Java 8 treść metody nie jest dozwolona w interfejsie. Ale od wersji Java 8 możemy zdefiniować domyślne lub statyczne metody wewnątrz interfejsu.
P # 2) Czy interfejs może mieć zmienne w Javie 8?
Odpowiedź: Możemy mieć stałe zmienne w Javie 8 używając statycznych i końcowych modyfikatorów. Ale nie możemy mieć zmiennych instancji w interfejsach Java. Każda próba zadeklarowania zmiennych instancji w interfejsie spowoduje błąd kompilatora.
Pytanie 3) Jakie są ulepszenia w interfejsach w Javie 8?
Odpowiedź: Najważniejszym ulepszeniem interfejsów w Javie 8 jest to, że w interfejsach dozwolone są metody statyczne i domyślne. Możemy zadeklarować metody jako statyczne lub domyślne i zdefiniować je wewnątrz interfejsu.
Q # 4) Czy możemy zastąpić domyślną metodę w interfejsie Java?
Odpowiedź: Nie. Przesłanianie domyślnej metody w interfejsie nie jest obowiązkowe. Dzieje się tak, ponieważ kiedy implementujemy interfejs w klasie, wówczas domyślna metoda klasy jest dostępna dla klasy implementacji. Stąd korzystając z obiektu klasy implementacyjnej, mamy dostęp do domyślnej metody interfejsu.
Pytanie 5) Czy interfejsy mogą mieć pola w Javie?
dlaczego Linux jest szybszy niż Windows
Odpowiedź: Tak, możemy mieć pola lub zmienne w interfejsach w Javie, ale domyślnie wszystkie te pola są statyczne, końcowe i publiczne.
Wniosek
W tym samouczku omówiliśmy zmiany wprowadzone w interfejsach w Javie 8. Java 8 wprowadziła statyczne i domyślne metody w interfejsach. Wcześniej mogliśmy mieć tylko abstrakcyjne metody w interfejsie. Ale począwszy od Java 8, możemy definiować domyślne i statyczne metody w Javie.
Ponadto Java 8 umożliwia stosowanie wyrażeń lambda z interfejsami funkcjonalnymi w Javie. Następnie omówiliśmy również klasy abstrakcyjne i interfejsy oraz sprawdziliśmy, kiedy użyć każdego z nich w Javie. Widzieliśmy również dziedziczenie wyliczeń w Javie.
Omówiliśmy również niektóre różnice między rozszerzeniami a implementacjami, klasą i interfejsem, abstrakcyjną klasą i interfejsem itp.
=> Sprawdź WSZYSTKIE samouczki Java tutaj.
rekomendowane lektury
- Interfejs Java i samouczek klasy abstrakcyjnej z przykładami
- Porównywalne i porównawcze interfejsy w Javie
- Interfejs ListIterator w Javie z przykładami
- Ustaw interfejs w języku Java: samouczek dotyczący zestawu Java z przykładami
- Interfejs markera w Javie: serializowalny i klonowalny
- Metoda Java String length () z przykładami
- Wdrażanie Java: tworzenie i wykonywanie pliku Java JAR
- Jak korzystać z metody toString w języku Java?