interface enhancements java 8 java functional interface
Denna handledning förklarar tilläggen till gränssnittet i Java 8 och skillnader mellan Java-begrepp som en abstrakt klass, utvidgar nyckelord etc. med gränssnitten:
Vi utforskade allt om Gränssnitt i Java i vår senaste handledning. Vi har introducerat och täckt de grundläggande begreppen för gränssnitt i Java inklusive flera gränssnitt.
Innan Java 8 fick gränssnitt endast abstrakta metoder och statiska och slutliga variabler. De abstrakta metoderna är som standard offentliga och måste åsidosättas av klassen som implementerar ett gränssnitt.
Så gränssnittet var huvudsakligen ett kontrakt och var endast involverat i konstanter (statiska och slutliga) och abstrakta metoder.
=> Ta en titt på Java-nybörjarguiden här.
Vad du kommer att lära dig:
- Gränssnittsändringar i Java 8
- Java 8 funktionella gränssnitt
- Klass Vs-gränssnitt i Java
- Java förlänger Vs-implementeringar
- Gränssnitt mot abstrakt klass i Java
- Slutsats
Gränssnittsändringar i Java 8
Java 8-versionen introducerar eller tillåter oss att ha statiska och standardmetoder i gränssnitten. Med standardmetoder i ett gränssnitt kan utvecklarna lägga till fler metoder för gränssnitten. På detta sätt stör de inte eller ändrar inte klasserna som implementerar gränssnittet.
Java 8 tillåter också att gränssnittet har en statisk metod. Statiska metoder är desamma som vi definierar i klasser. Observera att den statiska metoden inte kan åsidosättas av klassen som implementerar gränssnittet.
Införandet av statiska och standardmetoder i gränssnittet gjorde det enklare att ändra gränssnitten utan problem och gjorde gränssnitten lättare att implementera.
Java 8 introducerar också 'Lambda Expressions' inuti funktionella gränssnitt. Dessutom finns det från Java 8 fler inbyggda funktionella gränssnitt som läggs till i Java.
I denna handledning kommer vi att diskutera alla dessa tillägg till gränssnitten i Java 8 och kommer också att diskutera några av skillnaderna mellan olika Java-begrepp som abstrakta klasser, utökar nyckelord etc. med gränssnitten.
Statisk metod i gränssnitt i Java
Gränssnitt kan också ha metoder som kan ha definitioner. Det här är de statiska metoderna i gränssnittet. De statiska metoderna definieras inuti gränssnittet och de kan inte åsidosättas eller ändras av de klasser som implementerar detta gränssnitt.
Vi kan kalla dessa statiska metoder direkt genom att använda gränssnittsnamnet.
Följande exempel visar användningen av den statiska metoden.
//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 ()'); } }
Produktion:
Ovanstående program har en TestInterface. Den har en statisk metod som heter 'static_print' och också en icke-statisk metod som heter nonstaticmethod.
Vi har implementerat TestInterface i TestClass och åsidosatt nonStaticMethod. Sedan i huvudmetoden kallar vi static_print-metoden direkt med TestInterface och nonStaticMethod med hjälp av objektet i TestClass.
Gränssnittets standardmetod
Som redan nämnts tillät gränssnitt före Java 8 endast abstrakta metoder. Då skulle vi ge denna metodimplementering i en separat klass. Om vi måste lägga till en ny metod i gränssnittet måste vi tillhandahålla dess implementeringskod i samma klass.
Därför, om vi ändrade gränssnittet genom att lägga till en metod till det, skulle också implementeringsklassen förändras.
Denna begränsning övervinndes av Java 8-versionen som gjorde att gränssnitten hade standardmetoder. Standardmetoderna ger på ett sätt bakåtkompatibilitet till de befintliga gränssnitten och vi behöver inte ändra implementeringsklassen. Standardmetoderna är också kända som 'virtuell förlängningsmetod' eller 'försvarsmetoder'.
Standardmetoder deklareras med hjälp av nyckelordet 'standard' i deklarationen. Deklarationen följs av definitionen av metoden. Vi kan åsidosätta standardmetoden eftersom den är tillgänglig för klassen som implementerar gränssnittet.
På samma sätt kan vi åberopa det med hjälp av implementeringsklassobjektet från gränssnittet direkt utan att åsidosätta det.
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(); } }
Produktion:
vad är en bin-filtyp
Ovanstående Java-program visar standardmetoden i gränssnittet. Observera att i huvudmetoden kan vi anropa standardmetoden för gränssnittet med hjälp av klassobjektet. Detta beror på att när klassen implementerar gränssnittet är standardmetoden också tillgänglig för klassen.
Notera: Vi kunde ha åsidosatt utskriftsmetoden () också i implementeringsklassen. Observera att om den åsidosätts, ändras åtkomstmodifieraren för standardmetoden till offentlig i implementeringsklassen.
Standardmetoder och flera arv
Det kan uppstå en situation vid flera gränssnitt där varje gränssnitt kan ha en standardmetod med samma prototyp. I ett sådant fall vet inte kompilatorn vilken metod som ska åberopas.
När denna situation uppstår där standardmetoden har samma prototyp i alla gränssnitt, är lösningen att åsidosätta metoden i implementeringsklassen så att när implementeringsklassobjektet anropar standardmetoden, åberopar kompilatorn metoden implementerad i klassen .
Följande Java-program visar användningen av standardmetoden med flera gränssnitt.
//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(); } }
Produktion:
hur man fixar odefinierad referens i c ++
I ovanstående program har vi åsidosatt standardmetoden (som har samma prototyp i båda gränssnitten) i implementeringsklassen. Detta sätt när vi kallar standardmetoden från huvudmetoden med hjälp av objektet för implementeringsklassen, åberopas den åsidosatta metoden.
Java 8 funktionella gränssnitt
Ett funktionellt gränssnitt är ett gränssnitt som bara har en abstrakt metod. Den kan innehålla valfritt antal standard- och statiska metoder men den abstrakta metoden den innehåller är exakt en. Dessutom kan ett funktionellt gränssnitt ha deklarationer av objektklassmetoder.
Funktionellt gränssnitt är känt som “ Gränssnitt för enkel abstrakt metod ”Eller” SAM-gränssnitt ”. SAM-gränssnittet är en ny funktion i Java.
I ett Java-program indikeras närvaron av ett funktionellt gränssnitt med hjälp av a @FunctionalInterface anteckning. När kompilatorn stöter på denna kommentar vet den att gränssnittet som följer denna kommentar är funktionellt. Följaktligen, om den innehåller mer än en abstrakt metod, blinkar det ett fel.
Anteckningen @FunctionalInterface är dock inte obligatoriskt i Java.
Följande program visar det funktionella gränssnittet i 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!!!'); } }
Produktion:
Det funktionella gränssnittet i ovanstående program har en enda abstrakt metod och har också en objektklassmetoddeklaration som hashCode, toString och lika. I klassen som implementerar detta gränssnitt åsidosätts den abstrakta metoden. I huvudmetoden skapar vi ett objekt för implementeringsklass och använder metoden.
Gränssnitt som Runnable och Comparable är exempel på funktionella gränssnitt som tillhandahålls i Java. Java 8 tillåter oss att tilldela lambdauttryck till det funktionella gränssnittsobjektet.
Följande exempelprogram visar detta.
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(); } }
Produktion:
Java 8 erbjuder också många inbyggda funktionella gränssnitt i paketet java.util.function.
Dessa inbyggda gränssnitt beskrivs nedan:
# 1) Predikera
Detta är ett funktionellt gränssnitt i Java som har ett enda abstrakt metodtest. Metoden 'test' returnerar det booleska värdet efter att ha testat det angivna argumentet.
Nedan visas prototypen för testmetoden för Predicate-gränssnittet.
public interface Predicate { public boolean test(T t); }
# 2) BinaryOperator
BinaryOperator-gränssnittet ger en abstrakt metod 'applicera' som accepterar två argument och returnerar ett resulterande värde av samma typ som argumenten.
Prototypen för acceptmetoden är:
public interface BinaryOperator { public T apply (T x, T y); }
# 3) Funktion
Funktionsgränssnittet är ett funktionellt gränssnitt som också har en abstrakt metod som heter ”applicera”. Denna tillämpningsmetod tar dock ett enda argument av typ T och returnerar ett värde av typ R.
Prototypen för appliceringsmetoden är som följer:
public interface Function { public R apply(T t); }
Följande Java-program visar ovanstående inbyggda funktionella gränssnittspredikat.
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); } } }
Produktion:
Som vi kan se i ovanstående program har vi en lista med strängar. Med hjälp av det funktionella gränssnittet Predicate testar vi om objektet i strängen börjar med M och om det gör det, skriver det ut namnet.
Klass Vs-gränssnitt i Java
Även om klass och gränssnitt är lika eftersom de har liknande syntax, har dessa två enheter fler skillnader än likheter.
Låt oss lista upp några av skillnaderna mellan klass och gränssnitt i Java.
Klass | Gränssnitt |
---|---|
Vi kan instantiera och skapa objekt från en klass. | Ett gränssnitt kan inte initieras. |
Nyckelordet 'klass' används för att skapa en klass. | Gränssnittet skapas med nyckelordet ”gränssnitt”. |
Klasser stöder inte flera arv i Java. | Gränssnitt stöder flera arv i Java. |
Klassen innehåller konstruktörerna. | Gränssnitt innehåller inte konstruktörer. |
Klassen kan inte innehålla abstrakta metoder. | Gränssnitt innehåller endast abstrakta metoder. |
Klassen kan ha variabler och metoder som är standard, offentliga, privata eller skyddade. | Gränssnittet har endast offentliga variabler och metoder som standard. |
Det är inte obligatoriskt att koppla icke-åtkomstmodifierare till variabler i klassen. | Gränssnitt kan ha variabler som antingen är statiska eller slutliga. |
Vi kan ärva en annan klass från en klass. | Vi kan inte ärva en klass från gränssnittet. |
Klassen kan ärvas med hjälp av nyckelordet ”förlänger”. | Gränssnittet kan implementeras av en annan klass med nyckelordet ”implementerar”. Det kan ärvas av ett annat gränssnitt med hjälp av 'extends' nyckelord. |
Java förlänger Vs-implementeringar
'Sträcker sig' | 'Redskap' |
---|---|
Gränssnitt stöder endast statiska och slutliga icke-åtkomstmodifierare. | Abstrakt stöder alla icke-åtkomstmodifierare som statisk, slutlig, icke-statisk och icke-slutlig. |
En klass använder ”utökar” nyckelord för att ärva från en annan klass. | Nyckelordet 'implementerar' används av en klass för att implementera ett gränssnitt. |
En klass som ärver en annan klass kan eller kanske inte åsidosätta alla metoderna i moderklassen. | Klassen som implementerar gränssnittet måste åsidosätta alla abstrakta metoder i gränssnittet. |
Vi kan bara utöka en klass åt gången med hjälp av nyckelordet extends. | Vi kan implementera flera gränssnitt med hjälp av nyckelordet ”implementerar”. |
Ett gränssnitt kan utöka ett annat gränssnitt med hjälp av 'utökar' nyckelord. | Ett gränssnitt kan inte implementera ett annat gränssnitt med hjälp av 'implementerar' nyckelord. |
Kan abstrakt klassimplementera gränssnitt i Java
Ja, en abstrakt klass kan implementera ett gränssnitt med nyckelordet ”implementerar”. Abstraktklassen behöver inte implementera alla abstrakta gränssnittsmetoder. Men totalt sett är det en bra designpraxis att ha ett gränssnitt med alla abstrakta metoder, sedan en abstrakt klass som implementerar detta gränssnitt och sedan de konkreta klasserna.
Nedan ges ett exempel på en sådan implementering i Java.
Här är java.util.List ett gränssnitt. Detta gränssnitt implementeras av java.util.AbstractList. Sedan utvidgas denna AbstractList-klass med två konkreta klasser, dvs LinkedList och ArrayList.
Om klasserna LinkedList och ArrayList hade implementerat List-gränssnittet direkt, skulle de behöva implementera alla abstrakta metoder för List-gränssnittet.
Men i det här fallet implementerar klassen AbstractList metoderna för List-gränssnittet och skickar dem vidare till LinkedList och ArrayList. Så här får vi fördelen att deklarera typ från gränssnittet och abstrakt klassflexibilitet för att implementera det vanliga beteendet.
När ska man använda abstrakt klass och gränssnitt i Java
Vi använder främst en abstrakt klass för att definiera ett standard- eller vanligt beteende hos barnklasserna som sträcker sig från denna abstrakta klass. Ett gränssnitt används för att definiera ett kontrakt mellan två system som interagerar i en applikation.
Vissa specifika situationer är perfekta för gränssnitt som ska användas och vissa problem som endast kan lösas med abstrakta klasser. I det här avsnittet kommer vi att diskutera när vi kan använda gränssnittet och när vi kan använda abstrakta klasser.
När ska man använda ett gränssnitt:
- Gränssnitt används främst när vi har en liten kortfattad funktionalitet att implementera.
- När vi implementerar API: er och vi vet att de inte kommer att ändras på ett tag, då går vi efter gränssnitt.
- Gränssnitt gör att vi kan implementera flera arv. Därför när vi behöver implementera flera arv i vår applikation, går vi efter gränssnitt.
- När vi har ett brett utbud av objekt är gränssnitt igen ett bättre val.
- Även när vi måste tillhandahålla en gemensam funktionalitet till många orelaterade klasser används fortfarande gränssnitt.
När ska man använda en abstrakt klass:
- Abstrakta klasser används främst när vi behöver använda arv i vår applikation.
- Eftersom gränssnitt handlar om offentliga metoder och variabler använder vi abstrakta klasser när vi vill använda icke-offentliga åtkomstmodifierare i vårt program.
- Om nya metoder måste läggas till är det bättre att göra det i en abstrakt klass än i gränssnittet. För om vi lägger till en ny metod i gränssnittet ändras hela implementeringen eftersom gränssnitt endast har metodprototyper och klassimplementering med gränssnittet kommer att ge implementeringen.
- Om vi vill att olika versioner av komponenterna ska utvecklas, går vi till abstrakt klass. Vi kan lättare ändra abstrakta klasser. Men gränssnitt kan inte ändras. Om vi vill ha en ny version måste vi skriva hela gränssnittet igen.
- När vi vill tillhandahålla en gemensam implementering för alla komponenter är abstraktklassen det bästa valet.
Gränssnitt mot abstrakt klass i Java
Nedan följer några av skillnaderna mellan gränssnitt och abstraktklasser i Java.
Gränssnitt | Abstrakt klass |
---|---|
Ett gränssnitt deklareras med hjälp av nyckelordet ”gränssnitt”. | En abstrakt klass förklaras med hjälp av 'abstrakt' nyckelordet. |
Gränssnittet kan implementeras med hjälp av nyckelordet ”implementerar”. | Sammanfattningen kan ärvas med hjälp av 'extends' nyckelord. |
Ett gränssnitt kan inte förlänga en klass eller implementera ett gränssnitt, det kan bara utöka ett annat gränssnitt. | En abstrakt klass kan utöka en klass eller implementera flera gränssnitt. |
Gränssnittsmedlemmar kan bara vara offentliga. | Abstrakta klassmedlemmar kan vara offentliga, privata eller skyddade. |
Ett gränssnitt kan inte användas för att ge en implementering. Det kan bara användas som en deklaration. | En abstrakt klass kan användas för att implementera gränssnittet. |
Flera arv kan uppnås med gränssnitt. | Abstraktklassen stöder inte flera arv. |
Gränssnitt kan bara ha abstrakta metoder. Från Java 8 kan den ha statiska metoder och standardmetoder. | En abstrakt klass kan ha en abstrakt eller icke-abstrakt metod. |
Enum Arv i Java
Vi har diskuterat enumdatatyper i vår diskussion om datatyper i Java. Alla enums sträcker sig från java.lang.Enum-klassen. Denna klass java.lang.Enum är en abstrakt klass.
Alla enum-klasser i Java är som standard också 'final'. Därför resulterar ett försök att ärva en klass från enumklasser i ett kompileringsfel.
Eftersom Java inte tillåter flera arv kan vi inte ärva enum-klass från någon annan klass, eftersom enum-klass redan ärver från java.lang.Enum. Emellertid kan enum-klasser implementera gränssnitt i Java och detta kallas Enum-arv i Java.
Nedan ges ett exempel på Enum Inheritance i 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 } }
Produktion:
Här har vi ett gränssnitt WeekDays med en abstrakt metod prototyp displaydays (). Sedan definierar vi en Enum-klassdagar som implementerar WeekDays-gränssnittet. Här definierar vi enumvärden från SÖNDAG till LÖRDAG och åsidosätter också visningsdagens metod.
Slutligen, i huvudmetoden, får vi tillgång till enum-värdet och visar det.
Vanliga frågor
F # 1) Vad händer om du ger en metodkropp i gränssnittet?
Svar: För Java-versioner före Java 8 är metodens kropp inte tillåten i gränssnittet. Men sedan Java 8 kan vi antingen definiera en standard eller statiska metoder inuti gränssnittet.
F # 2) Kan ett gränssnitt ha variabler i Java 8?
Svar: Vi kan ha konstanta variabler i Java 8 med statiska och slutliga modifierare. Men vi kan inte ha instansvariabler i Java-gränssnitt. Varje försök att deklarera instansvariabler i ett gränssnitt kommer att resultera i ett kompileringsfel.
F # 3) Vilka är förbättringarna i gränssnitt i Java 8?
Svar: Den viktigaste förbättringen för gränssnitt i Java 8 är att statiska metoder och standardmetoder är tillåtna i gränssnitt. Vi kan få metoder deklarerade som statiska eller standard och definiera dem i gränssnittet.
F # 4) Kan vi åsidosätta standardmetoden i Java-gränssnittet?
Svar: Nej. Det är inte obligatoriskt att åsidosätta standardmetoden i gränssnittet. Detta beror på att när vi implementerar ett gränssnitt i en klass, är standardmetoden för klassen tillgänglig för implementeringsklassen. Därför använder vi objektet för implementeringsklassen, vi kan komma åt standardmetoden för gränssnittet.
F # 5) Kan gränssnitt ha fält i Java?
vilket av följande gäller för ett systemtest?
Svar: Ja, vi kan ha fält eller variabler i gränssnitt i Java men som standard är alla dessa fält statiska, slutliga och offentliga.
Slutsats
I denna handledning har vi diskuterat de ändringar som gjorts i gränssnitt i Java 8. Java 8 introducerade statiska och standardmetoder i gränssnitt. Tidigare kunde vi bara ha abstrakta metoder i gränssnittet. Men från och med Java 8 kan vi definiera standard- och statiska metoder i Java.
Java 8 tillåter också användning av lambdauttryck med de funktionella gränssnitten i Java. Sedan diskuterade vi också abstrakta klasser och gränssnitt och såg när vi skulle använda var och en av dem i Java. Vi har också sett enum-arvet i Java.
Vi diskuterade också några av skillnaderna mellan förlängningar och redskap, klass och gränssnitt, abstrakt klass och gränssnitt etc.
=> Kontrollera ALLA Java-handledning här.
Rekommenderad läsning
- Java-gränssnitt och abstrakt klasshandledning med exempel
- Jämförbara och komparatorgränssnitt i Java
- ListIterator-gränssnitt i Java med exempel
- Ställ in gränssnitt i Java: Java Set Tutorial med exempel
- Markörgränssnitt i Java: Serialiserbart och klonbart
- Java Stränglängd () Metod med exempel
- Java-distribution: Skapande och utförande av Java JAR-fil
- Hur man använder Java toString Method?