interface enhancements java 8 java functional interface
Tento kurz vysvětluje dodatky k rozhraní v prostředí Java 8 a rozdíly mezi koncepty Java, jako je abstraktní třída, rozšiřuje klíčové slovo atd. S rozhraními:
Vše jsme prozkoumali Rozhraní v Javě v našem posledním tutoriálu. Zavedli jsme a pokryli základní koncepty rozhraní v Javě, včetně více rozhraní.
Před verzí Java 8 bylo povoleno, aby rozhraní měla pouze abstraktní metody a statické a konečné proměnné. Abstraktní metody jsou ve výchozím nastavení veřejné a musí být přepsány třídou, která implementuje rozhraní.
Rozhraní tedy bylo hlavně smlouvou a týkalo se pouze konstant (statických a konečných) a abstraktních metod.
=> Prohlédněte si příručku Java Beginners Guide zde.
Co se naučíte:
- Změny rozhraní v prostředí Java 8
- Funkční rozhraní Java 8
- Rozhraní třídy Vs v Javě
- Java rozšiřuje Vs implementace
- Rozhraní Vs Abstraktní třída v Javě
- Závěr
Změny rozhraní v prostředí Java 8
Vydání Java 8 zavádí nebo nám umožňuje mít v rozhraních statické a výchozí metody. Pomocí výchozích metod v rozhraní mohou vývojáři do rozhraní přidat další metody. Tímto způsobem nenarušují ani nemění třídy, které implementují rozhraní.
Java 8 také umožňuje, aby rozhraní mělo statickou metodu. Statické metody jsou stejné jako ty, které definujeme ve třídách. Všimněte si, že statická metoda nemůže být přepsána třídou, která implementuje rozhraní.
Zavedení statických a výchozích metod v rozhraní usnadnilo bezproblémovou změnu rozhraní a také usnadnilo implementaci rozhraní.
Java 8 také zavádí „Lambda Expressions“ do funkčních rozhraní. Kromě toho je od Javy 8 dále přidáváno více vestavěných funkčních rozhraní v Javě.
V tomto tutoriálu probereme všechny tyto dodatky k rozhraním v Javě 8 a probereme také některé rozdíly mezi různými pojmy Java, jako jsou abstraktní třídy, klíčové slovo extends atd. S rozhraními.
Statická metoda v rozhraní v Javě
Rozhraní mohou mít také metody, které mohou mít definice. Jedná se o statické metody v rozhraní. Statické metody jsou definovány uvnitř rozhraní a nemohou být přepsány nebo změněny třídami, které implementují toto rozhraní.
Tyto statické metody můžeme zavolat přímo pomocí názvu rozhraní.
Následující příklad ukazuje použití statické metody.
//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 ()'); } }
Výstup:
Výše uvedený program má TestInterface. Má statickou metodu s názvem „static_print“ a také nestatickou metodu s názvem nonstaticmethod.
Implementovali jsme TestInterface v TestClass a přepsali nonStaticMethod. Pak v hlavní metodě voláme static_print metodu přímo pomocí TestInterface a nonStaticMethod pomocí objektu TestClass.
Výchozí metoda rozhraní
Jak již bylo zmíněno, rozhraní před Java 8 povolovala pouze abstraktní metody. Pak bychom tuto implementaci metody poskytli v samostatné třídě. Pokud bychom do rozhraní museli přidat novou metodu, musíme poskytnout její implementační kód ve stejné třídě.
Pokud bychom tedy změnili rozhraní přidáním metody, změnila by se také implementační třída.
Toto omezení bylo překonáno verzí Java 8, která umožňovala rozhraním mít výchozí metody. Výchozí metody způsobem poskytují zpětnou kompatibilitu s existujícími rozhraními a nemusíme měnit implementační třídu. Výchozí metody jsou také známé jako „metoda virtuálního rozšíření“ nebo „metody obránce“.
Výchozí metody jsou deklarovány pomocí klíčového slova „default“ v deklaraci. Za deklarací následuje definice metody. Můžeme přepsat výchozí metodu, protože je k dispozici třídě, která implementuje rozhraní.
Stejným způsobem jej můžeme vyvolat pomocí objektu třídy implementace z rozhraní přímo, aniž bychom jej přepsali.
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(); } }
Výstup:
otázky k rozhovoru o html a css
Výše uvedený program Java demonstruje výchozí metodu v rozhraní. V hlavní metodě si všimněte, že můžeme volat výchozí metodu rozhraní pomocí objektu třídy. Důvodem je, že jak třída implementuje rozhraní, je pro třídu k dispozici také výchozí metoda.
Poznámka: Mohli jsme přepsat metodu print () také ve třídě implementace. Všimněte si, že pokud je přepsáno, pak se modifikátor přístupu výchozí metody změní na veřejnou ve třídě implementace.
Výchozí metody a vícenásobná dědičnost
Může nastat situace v případě více rozhraní, kde každé rozhraní může mít výchozí metodu se stejným prototypem. V takovém případě kompilátor neví, kterou metodu vyvolat.
Když nastane tato situace, ve které výchozí metoda má stejný prototyp ve všech rozhraních, je řešením přepsat metodu ve třídě implementace, takže když objekt třídy implementace zavolá výchozí metodu, kompilátor vyvolá metodu implementovanou ve třídě .
binární strom c ++ kód
Následující program Java demonstruje použití výchozí metody s více rozhraními.
//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(); } }
Výstup:
Ve výše uvedeném programu jsme přepsali výchozí metodu (která má stejný prototyp v obou rozhraních) v implementační třídě. Tímto způsobem, když voláme výchozí metodu z hlavní metody pomocí objektu třídy implementace, je vyvolána přepsaná metoda.
Funkční rozhraní Java 8
Funkční rozhraní je rozhraní, které má pouze jednu abstraktní metodu. Může obsahovat libovolný počet výchozích a statických metod, ale abstraktní metoda, kterou obsahuje, je přesně jedna. Funkční rozhraní může navíc obsahovat deklarace metod třídy objektů.
Funkční rozhraní je známé jako „ Rozhraní jediné abstraktní metody “Nebo„ Rozhraní SAM “. Rozhraní SAM je v Javě novou funkcí.
V programu Java je přítomnost funkčního rozhraní indikována pomocí a @Funkčnírozhraní anotace. Když kompilátor narazí na tuto anotaci, pak ví, že rozhraní, které následuje po této anotaci, je funkční. Pokud tedy obsahuje více než jednu abstraktní metodu, bliká chyba.
Anotace @Funkčnírozhraní v Javě to však není povinné.
Následující program demonstruje funkční rozhraní v Javě:
//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!!!'); } }
Výstup:
Funkční rozhraní ve výše uvedeném programu má jedinou abstraktní metodu a má také deklaraci metody třídy objektu jako hashCode, toString a equals. Ve třídě, která implementuje toto rozhraní, je přepsána abstraktní metoda. V hlavní metodě vytvoříme objekt třídy implementace a použijeme metodu.
Rozhraní jako Runnable a Comparable jsou příklady funkčních rozhraní poskytovaných v Javě. Java 8 nám umožňuje přiřadit výrazy lambda k objektu funkčního rozhraní.
Následující ukázkový program to ukazuje.
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(); } }
Výstup:
Java 8 také poskytuje mnoho vestavěných funkčních rozhraní v balíčku java.util.function.
Tato integrovaná rozhraní jsou popsána níže:
# 1) Predikát
Toto je funkční rozhraní v Javě, které má jediný abstraktní test metod. Metoda ‘test’ vrací booleovskou hodnotu po testování zadaného argumentu.
Níže je uveden prototyp testovací metody rozhraní Predicate.
public interface Predicate { public boolean test(T t); }
# 2) BinaryOperator
Rozhraní BinaryOperator poskytuje abstraktní metodu 'apply', která přijímá dva argumenty a vrací výslednou hodnotu stejného typu jako argumenty.
Prototyp metody přijetí je:
public interface BinaryOperator { public T apply (T x, T y); }
# 3) Funkce
Funkční rozhraní je funkční rozhraní, které má také abstraktní metodu s názvem „použít“. Tato metoda apply však přebírá jeden argument typu T a vrací hodnotu typu R.
Prototyp metody Apply je následující:
public interface Function { public R apply(T t); }
Následující program Java demonstruje výše uvedený vestavěný predikát funkčního rozhraní.
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); } } }
Výstup:
Jak vidíme ve výše uvedeném programu, máme seznam řetězců. Pomocí funkčního rozhraní Predicate otestujeme, zda položka v řetězci začíná písmenem M a pokud ano, vytiskne název.
Rozhraní třídy Vs v Javě
Ačkoli třída a rozhraní jsou podobné, protože mají podobnou syntaxi, tyto dvě entity mají více rozdílů než podobností.
Pojďme si vyjmenovat některé rozdíly mezi třídou a rozhraním v Javě.
Třída | Rozhraní |
---|---|
Můžeme vytvořit instanci a vytvořit objekty z třídy. | Nelze vytvořit instanci rozhraní. |
Klíčové slovo „třída“ se používá k vytvoření třídy. | Rozhraní se vytváří pomocí klíčového slova „interface“. |
Třídy nepodporují vícenásobné dědění v Javě. | Rozhraní podporují vícenásobnou dědičnost v Javě. |
Třída obsahuje konstruktory. | Rozhraní neobsahují konstruktory. |
Třída nemůže obsahovat abstraktní metody. | Rozhraní obsahují pouze abstraktní metody. |
Třída může mít proměnné a metody, které jsou výchozí, veřejné, soukromé nebo chráněné. | Ve výchozím nastavení má rozhraní pouze veřejné proměnné a metody. |
Není povinné přidružovat modifikátory nepřístupu k proměnným třídy. | Rozhraní mohou mít proměnné, které jsou statické nebo konečné. |
Z třídy můžeme zdědit další třídu. | Z rozhraní nemůžeme zdědit třídu. |
Třídu lze zdědit pomocí klíčového slova „extends“. | Rozhraní může být implementováno jinou třídou pomocí klíčového slova ‘implements’. Může být zděděno jiným rozhraním pomocí klíčového slova „extends“. |
Java rozšiřuje Vs implementace
'rozšiřuje' | ‚Nářadí ' |
---|---|
Rozhraní podporují pouze statické a konečné modifikátory nepřístupu. | Abstrakt podporuje všechny nepřístupné modifikátory, jako jsou statické, konečné, nestatické a nekoncové. |
Třída používá k dědění z jiné třídy klíčové slovo „extends“. | Klíčové slovo „implementuje“ používá třída k implementaci rozhraní. |
Třída, která dědí jinou třídu, může nebo nemusí přepsat všechny metody nadřazené třídy. | Třída implementující rozhraní musí přepsat všechny abstraktní metody rozhraní. |
Pomocí klíčového slova extends můžeme rozšířit pouze jednu třídu najednou. | Pomocí klíčového slova „implementuje“ můžeme implementovat více rozhraní. |
Rozhraní může rozšířit další rozhraní pomocí klíčového slova „extends“. | Rozhraní nemůže implementovat jiné rozhraní pomocí klíčových slov „implementuje“. |
Může abstraktní třída implementovat rozhraní v Javě
Ano, abstraktní třída může implementovat rozhraní pomocí klíčového slova ‘implements’. Abstraktní třída nemusí implementovat všechny abstraktní metody rozhraní. Ale celkově je dobrým designovým postupem mít rozhraní se všemi abstraktními metodami, pak abstraktní třídu implementující toto rozhraní a pak konkrétní třídy.
Níže je uveden příklad takové implementace v Javě.
Zde java.util.List je rozhraní. Toto rozhraní implementuje java.util.AbstractList. Pak je tato třída AbstractList rozšířena o dvě konkrétní třídy, tj. LinkedList a ArrayList.
Pokud třídy LinkedList a ArrayList implementovaly rozhraní List přímo, pak by musely implementovat všechny abstraktní metody rozhraní List.
Ale v tomto případě třída AbstractList implementuje metody rozhraní List a předává je LinkedList a ArrayList. Tady tedy máme výhodu deklarování typu z rozhraní a flexibility abstraktní třídy při implementaci společného chování.
Kdy použít abstraktní třídu a rozhraní v Javě
Používáme hlavně abstraktní třídu k definování výchozího nebo běžného chování podřízených tříd, které se rozšíří z této abstraktní třídy. Rozhraní se používá k definování smlouvy mezi dvěma systémy, které interagují v aplikaci.
Určité konkrétní situace jsou ideální pro použití rozhraní a určité problémy, které lze vyřešit pouze pomocí abstraktních tříd. V této části probereme, kdy můžeme použít rozhraní a kdy můžeme použít abstraktní třídy.
Kdy použít rozhraní:
- Rozhraní se používají hlavně tehdy, když máme k implementaci malou stručnou funkčnost.
- Když implementujeme API a víme, že se na chvíli nezmění, pak se vydáme na rozhraní.
- Rozhraní nám umožňují implementovat více dědičností. Když tedy potřebujeme v naší aplikaci implementovat vícenásobné dědění, jdeme na rozhraní.
- Když máme širokou škálu objektů, opět jsou lepší volbou rozhraní.
- Také když musíme poskytnout společnou funkčnost mnoha nesouvisejícím třídám, použijí se stále rozhraní.
Kdy použít abstraktní třídu:
- Abstraktní třídy se používají hlavně tehdy, když v naší aplikaci potřebujeme použít dědičnost.
- Protože rozhraní se zabývají veřejnými metodami a proměnnými, kdykoli v našem programu chceme použít neveřejné modifikátory přístupu, používáme abstraktní třídy.
- Pokud je třeba přidat nové metody, je lepší to udělat v abstraktní třídě než v rozhraní. Protože pokud do rozhraní přidáme novou metodu, celá implementace se změní, protože rozhraní mají pouze prototypy metod a implementaci zajistí implementace třídy pomocí rozhraní.
- Pokud chceme, aby se vyvíjely různé verze komponent, přejdeme na abstraktní třídu. Můžeme změnit abstraktní třídy snadněji. Rozhraní však nelze změnit. Pokud chceme novou verzi, musíme znovu napsat celé rozhraní.
- Když chceme poskytnout společnou implementaci pro všechny komponenty, pak je nejlepší volbou abstraktní třída.
Rozhraní Vs Abstraktní třída v Javě
Níže uvádíme některé rozdíly mezi třídami Interfaces a Abstract v Javě.
Rozhraní | Abstraktní třída |
---|---|
Rozhraní je deklarováno pomocí klíčového slova „interface“. | Abstraktní třída je deklarována pomocí klíčového slova „abstract“. |
Rozhraní lze implementovat pomocí klíčového slova „implementuje“. | Abstrakt lze zdědit pomocí klíčového slova „extends“. |
Rozhraní nemůže rozšířit třídu nebo implementovat rozhraní, může rozšířit pouze jiné rozhraní. | Abstraktní třída může rozšířit třídu nebo implementovat více rozhraní. |
Členové rozhraní mohou být pouze veřejní. | Členové abstraktní třídy mohou být veřejní, soukromí nebo chráněni. |
K zajištění implementace nelze použít rozhraní. Lze jej použít pouze jako prohlášení. | Pro implementaci rozhraní lze použít abstraktní třídu. |
Více rozhraní lze dosáhnout pomocí rozhraní. | Abstraktní třída nepodporuje vícenásobné dědění. |
Rozhraní mohou mít pouze abstraktní metody. Z prostředí Java 8 může mít statické a výchozí metody. | Abstraktní třída může mít abstraktní nebo neabstraktní metodu. |
Enum Inheritance In Java
V naší diskusi o datových typech v jazyce Java jsme diskutovali o datových typech enum. Všechny výčty sahají od třídy java.lang.Enum. Tato třída java.lang.Enum je abstraktní třída.
Všechny třídy výčtu v Javě jsou také ve výchozím nastavení „konečné“. Pokus o zdědění třídy z jakýchkoli tříd výčtu tedy vede k chybě kompilátoru.
Protože Java nepovoluje vícenásobné dědění, nemůžeme dědit třídu enum z žádné jiné třídy, protože třída enum již dědí z java.lang.Enum. Třídy enum však mohou implementovat rozhraní v Javě a toto se nazývá Enum dědičnost v Javě.
Níže je uveden příklad Enum Inheritance v Javě.
//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 } }
Výstup:
Tady máme rozhraní WeekDays s prototypem abstraktní metody displaydays (). Poté definujeme třídu výčtu Days, která implementuje rozhraní WeekDays. Zde definujeme výčtové hodnoty od NEDĚLE do SOBOTY a také přepíšeme metodu displaydays.
Nakonec v hlavní metodě přistupujeme k hodnotě výčtu a zobrazíme ji.
Často kladené otázky
Otázka č. 1) Co se stane, když v rozhraní zadáte tělo metody?
Odpovědět: U verzí Java před verzí Java 8 není tělo metody povoleno v rozhraní. Ale od prostředí Java 8 můžeme v rozhraní definovat výchozí nebo statické metody.
Otázka 2) Může rozhraní obsahovat proměnné v Javě 8?
Odpovědět: Můžeme mít konstantní proměnné v Javě 8 pomocí statických a konečných modifikátorů. V rozhraní Java ale nemůžeme mít proměnné instance. Jakýkoli pokus o deklaraci proměnných instance v rozhraní bude mít za následek chybu kompilátoru.
Otázka č. 3) Jaká jsou vylepšení rozhraní v prostředí Java 8?
Odpovědět: Nejdůležitějším vylepšením rozhraní v prostředí Java 8 je to, že v rozhraních jsou povoleny statické a výchozí metody. Můžeme mít metody deklarované jako statické nebo výchozí a definovat je uvnitř rozhraní.
Otázka č. 4) Můžeme přepsat výchozí metodu v rozhraní Java?
Odpovědět: Ne. Není povinné přepsat výchozí metodu v rozhraní. Je to proto, že když implementujeme rozhraní ve třídě, pak je výchozí metoda třídy přístupná implementační třídě. Proto pomocí objektu třídy implementace můžeme přistupovat k výchozí metodě rozhraní.
Otázka č. 5) Mohou rozhraní obsahovat pole v Javě?
nejlepší sluchátka pro virtuální realitu pro Xbox One
Odpovědět: Ano, můžeme mít pole nebo proměnné v rozhraních v Javě, ale ve výchozím nastavení jsou všechna tato pole statická, konečná a veřejná.
Závěr
V tomto tutoriálu jsme probrali změny provedené v rozhraních v Javě 8. Java 8 představila v rozhraních statické a výchozí metody. Dříve jsme v rozhraní mohli mít pouze abstraktní metody. Ale od Javy 8 a dále můžeme v Javě definovat výchozí a statické metody.
Java 8 také umožňuje použití výrazů lambda s funkčními rozhraními v Javě. Pak jsme také diskutovali o abstraktních třídách a rozhraních a zjistili jsme, kdy je použít každý z nich v Javě. Také jsme viděli dědičnost výčtu v Javě.
Diskutovali jsme také o některých rozdílech mezi extends a implements, třídou a rozhraním, abstraktní třídou a rozhraním atd.
=> Zkontrolujte VŠECHNY výukové programy Java zde.
Doporučené čtení
- Výukový program pro rozhraní Java a abstraktní třídu s příklady
- Srovnatelná a komparační rozhraní v Javě
- Rozhraní ListIterator v Javě s příklady
- Set Interface In Java: Java Set Tutorial With examples
- Rozhraní značek v Javě: Serializovatelné a klonovatelné
- Metoda Java String length () S příklady
- Implementace Java: Vytvoření a spuštění souboru Java JAR
- Jak používat metodu Java toString?