Java 8 interface-wijzigingen omvatten statische methoden en standaardmethoden in interfaces. Voor Java 8 konden we alleen methodedeclaraties hebben in de interfaces. Maar vanaf Java 8 kunnen we standaardmethoden en statische methoden in de interfaces hebben.
Java 8 Interface
Het ontwerpen van interfaces is altijd een lastige klus geweest, omdat als we extra methoden aan de interfaces willen toevoegen, dit wijzigingen vereist in alle implementerende klassen. Naarmate een interface ouder wordt, kan het aantal klassen dat het implementeert, groeien tot een punt waarop het niet mogelijk is om interfaces uit te breiden. Daarom bieden de meeste frameworks bij het ontwerpen van een toepassing een basisklasse-implementatie en breiden we deze vervolgens uit en overschrijven we methoden die van toepassing zijn op onze toepassing. Laten we eens kijken naar de standaardmethoden van het interface en de statische methoden van het interface, en de redenering achter hun introductie in de Java 8 interface-wijzigingen.
Standaardmethode van Java-interface
Voor het maken van een standaardmethode in een Java-interface moeten we het sleutelwoord “default” gebruiken samen met de methodehandtekening. Bijvoorbeeld,
package com.journaldev.java8.defaultmethod;
public interface Interface1 {
void method1(String str);
default void log(String str){
System.out.println("I1 logging::"+str);
}
}
Let op dat log(String str) de standaardmethode is in Interface1
. Wanneer een klasse Interface1 implementeert, is het niet verplicht om implementaties te bieden voor standaardmethoden van de interface. Deze functie helpt ons bij het uitbreiden van interfaces met aanvullende methoden, alles wat we nodig hebben is een standaardimplementatie te bieden. Laten we zeggen dat we nog een interface hebben met de volgende methoden:
package com.journaldev.java8.defaultmethod;
public interface Interface2 {
void method2();
default void log(String str){
System.out.println("I2 logging::"+str);
}
}
We weten dat Java ons niet toestaat om meerdere klassen uit te breiden omdat dit resulteert in het “Diamond-probleem” waarbij de compiler niet kan beslissen welke superklas-methode moet worden gebruikt. Met de standaardmethoden zou het diamond-probleem ook voor interfaces ontstaan. Omdat als een klasse zowel Interface1
als Interface2
implementeert en de gemeenschappelijke standaardmethode niet implementeert, de compiler niet kan beslissen welke te kiezen. Het uitbreiden van meerdere interfaces is een integraal onderdeel van Java, je zult het vinden in de kern Java-klassen evenals in de meeste bedrijfsapplicaties en -frameworks. Dus om ervoor te zorgen dat dit probleem niet optreedt in interfaces, is het verplicht gesteld om implementaties te bieden voor gemeenschappelijke standaardmethoden van interfaces. Dus als een klasse beide bovenstaande interfaces implementeert, moet het implementaties bieden voor log()
methode, anders zal de compiler een compileerfout genereren. Een eenvoudige klasse die zowel Interface1
als Interface2
implementeert, zal zijn:
package com.journaldev.java8.defaultmethod;
public class MyClass implements Interface1, Interface2 {
@Override
public void method2() {
}
@Override
public void method1(String str) {
}
@Override
public void log(String str){
System.out.println("MyClass logging::"+str);
Interface1.print("abc");
}
}
Belangrijke punten over standaardmethoden van Java-interfaces:
- interface: Java-interface standaardmethoden zullen ons helpen bij het uitbreiden van interfaces zonder de angst voor het breken van implementatieklassen.
- Java-interface standaardmethoden hebben de verschillen tussen interfaces en abstracte klassen overbrugd.
- Java 8-interface standaardmethoden zullen ons helpen bij het vermijden van hulpprogrammaklassen, zoals alle methoden van de Collections-klasse kunnen worden geleverd in de interfaces zelf.
- Java-interface standaardmethoden zullen ons helpen bij het verwijderen van basismethoden, we kunnen standaardimplementatie bieden en de implementatieklassen kunnen kiezen welke ze willen overschrijven.
- Een van de belangrijkste redenen voor het introduceren van standaardmethoden in interfaces is het verbeteren van de Collections API in Java 8 om lambda-uitdrukkingen te ondersteunen.
- Als een klasse in de hiërarchie een methode heeft met dezelfde handtekening, worden standaardmethoden irrelevant. Een standaardmethode kan geen methode van
java.lang.Object
overschrijven. De redenering is heel eenvoudig, omdat Object de basisklasse is voor alle Java-klassen. Zelfs als we Object-methoden als standaardmethoden definiëren in interfaces, zijn ze nutteloos omdat de Object-methode altijd zal worden gebruikt. Daarom kunnen we om verwarring te voorkomen geen standaardmethoden hebben die Object-methoden overschrijven. - Java-interface standaardmethoden worden ook wel Defender-methoden of Virtuele extensiemethoden genoemd.
Java Interface Statische Methode
Een Java-interface-statische methode is vergelijkbaar met een standaardmethode, behalve dat we ze niet kunnen overschrijven in de implementatieklassen. Deze functie helpt ons om ongewenste resultaten te vermijden in het geval van een slechte implementatie in implementatieklassen. Laten we hier eens naar kijken aan de hand van een eenvoudig voorbeeld.
package com.journaldev.java8.staticmethod;
public interface MyData {
default void print(String str) {
if (!isNull(str))
System.out.println("MyData Print::" + str);
}
static boolean isNull(String str) {
System.out.println("Interface Null Check");
return str == null ? true : "".equals(str) ? true : false;
}
}
Laten we nu eens kijken naar een implementatieklasse die de methode isNull() heeft met een slechte implementatie.
package com.journaldev.java8.staticmethod;
public class MyDataImpl implements MyData {
public boolean isNull(String str) {
System.out.println("Impl Null Check");
return str == null ? true : false;
}
public static void main(String args[]){
MyDataImpl obj = new MyDataImpl();
obj.print("");
obj.isNull("abc");
}
}
Let op dat isNull(String str)
een eenvoudige klassenmethode is, deze overschrijft de interface-methode niet. Als we bijvoorbeeld @Override-annotatie toevoegen aan de isNull()-methode, leidt dit tot een compilerfout. Als we nu de toepassing uitvoeren, krijgen we de volgende uitvoer.
Interface Null Check
Impl Null Check
Als we de interface-methode van statisch naar standaard maken, krijgen we de volgende uitvoer.
Impl Null Check
MyData Print::
Impl Null Check
Java-interface-statische methode is alleen zichtbaar voor interfacemethoden; als we de isNull()-methode uit de klasse MyDataImpl
verwijderen, kunnen we deze niet gebruiken voor het object MyDataImpl
. Net als andere statische methoden kunnen we echter interfacemethoden met statische methode gebruiken met de klassenaam. Bijvoorbeeld, een geldige verklaring zal zijn:
boolean result = MyData.isNull("abc");
Belangrijke punten over Java-interface-statische methode:
- Een Java-interface-statische methode is onderdeel van de interface, we kunnen deze niet gebruiken voor objecten van implementatieklassen.
- Java-interface-statische methoden zijn handig voor het leveren van hulpprogramma-methoden, zoals null-controle, sorteren van collecties, enz.
- Java-interface statische methode helpt ons bij het bieden van beveiliging door implementatieklassen niet toe te staan deze te overschrijven.
- We kunnen geen interface statische methode definiëren voor Object-klassenmethoden, we krijgen een compilerfout met de melding “Deze statische methode kan de instantiemethode van Object niet verbergen”. Dit is niet toegestaan in Java, omdat Object de basisklasse is voor alle klassen en we geen statische methode op klassen-niveau en een andere instantiemethode met dezelfde handtekening kunnen hebben.
- We kunnen Java-interface statische methoden gebruiken om hulpprogrammaklassen zoals Collections te verwijderen en alle statische methoden naar de overeenkomstige interface te verplaatsen, dat zou gemakkelijk te vinden en te gebruiken zijn.
Java Functionele Interfaces
Voor ik de post afsluit, wil ik graag een korte introductie geven over Functionele interfaces. Een interface met precies één abstracte methode staat bekend als Functionele Interface. Een nieuwe annotatie @FunctionalInterface is geïntroduceerd om een interface als Functionele Interface te markeren. De @FunctionalInterface-annotatie is een faciliteit om per ongeluk toevoegen van abstracte methoden in de functionele interfaces te voorkomen. Het is optioneel maar een goede praktijk om het te gebruiken. Functionele interfaces zijn langverwachte en zeer gewilde functies van Java 8 omdat het ons in staat stelt om lambda-expressies te gebruiken om ze te instantiëren. Een nieuwe package java.util.function
met een hoop functionele interfaces zijn toegevoegd om doeltypes te bieden voor lambda-expressies en methodereferenties. We zullen in toekomstige posts kijken naar functionele interfaces en lambda-expressies.