Nieuwe functies in Java 8

1. Overzicht

In dit artikel zullen we een korte blik werpen op enkele van de meest interessante nieuwe functies in Java 8.

We zullen het hebben over: standaard en statische interface-methoden, methodeverwijzing en optioneel.

We hebben al enkele functies van de release van Java 8 besproken - stream-API, lambda-expressies en functionele interfaces - omdat het uitgebreide onderwerpen zijn die een aparte kijk verdienen.

2. Standaardinterface en statische methoden

Vóór Java 8 konden interfaces alleen openbare abstracte methoden hebben. Het was niet mogelijk om nieuwe functionaliteit aan de bestaande interface toe te voegen zonder alle implementatieklassen te dwingen een implementatie van de nieuwe methoden te maken, noch was het mogelijk om interfacemethoden te creëren met een implementatie.

Vanaf Java 8 kunnen interfaces statisch en standaard methoden die, ondanks dat ze in een interface zijn gedeclareerd, een gedefinieerd gedrag hebben.

2.1. Statische methode

Beschouw de volgende methode van de interface (laten we deze interface noemen Voertuig):

static String producer () {retourneer "N&F Vehicles"; }

De statische producent() methode is alleen beschikbaar via en binnen een interface. Het kan niet worden overschreven door een implementerende klasse.

Om het buiten de interface te noemen, moet de standaardbenadering voor statische methodeaanroep worden gebruikt:

String producer = Vehicle.producer ();

2.2. Standaardmethode

Standaardmethoden worden gedeclareerd met behulp van het nieuwe standaard trefwoord. Deze zijn toegankelijk via het exemplaar van de implementatieklasse en kunnen worden overschreven.

Laten we een standaard methode naar onze Voertuig interface, die ook een oproep doet naar de statisch methode van deze interface:

default String getOverview () {return "ATV gemaakt door" + producer (); }

Stel dat deze interface wordt geïmplementeerd door de klas VoertuigImpl. Voor het uitvoeren van het standaard methode moet een instantie van deze klasse worden gemaakt:

Voertuigvoertuig = nieuwe VehicleImpl (); String overzicht = vehicle.getOverview ();

3. Methodeverwijzingen

Methodeverwijzing kan worden gebruikt als een korter en beter leesbaar alternatief voor een lambda-expressie die alleen een bestaande methode aanroept. Er zijn vier varianten van methodeverwijzingen.

3.1. Verwijzing naar een statische methode

De verwijzing naar een statische methode bevat de volgende syntaxis: ContainingClass :: methodName.

Laten we proberen alle lege strings in de Lijst met behulp van Stream API.

boolean isReal = list.stream (). anyMatch (u -> User.isRealUser (u));

Bekijk lambda-uitdrukking in de anyMatch () methode, het maakt gewoon een oproep naar een statische methode isRealUser (gebruiker gebruiker) van de Gebruiker klasse. Het kan dus worden vervangen door een verwijzing naar een statische methode:

boolean isReal = list.stream (). anyMatch (Gebruiker :: isRealUser);

Dit type code ziet er veel informatiever uit.

3.2. Verwijzing naar een instantiemethode

De verwijzing naar een instantiemethode bevat de volgende syntaxis: containingInstance :: methodName. De volgende methode voor codeaanroepen isLegalName (tekenreeks) van het type Gebruiker die een invoerparameter valideert:

Gebruiker gebruiker = nieuwe gebruiker (); boolean isLegalName = list.stream (). anyMatch (gebruiker :: isLegalName); 

3.3. Verwijzing naar een instantiemethode van een object van een bepaald type

Deze referentiemethode heeft de volgende syntaxis: ContainingType :: methodName. Een voorbeeld::

long count = list.stream (). filter (String :: isEmpty) .count ();

3.4. Verwijzing naar een constructor

Een verwijzing naar een constructor heeft de volgende syntaxis: Naam van de klasse::nieuw. Omdat de constructor in Java een speciale methode is, kan er met behulp van nieuwals een methode naam.

Stream stream = list.stream (). Map (Gebruiker :: nieuw);

4. Optioneel

Voordat Java 8 ontwikkelaars de waarden waarnaar ze verwezen zorgvuldig moesten valideren, vanwege de mogelijkheid om het NullPointerException (NPE). Al deze controles vereisten een behoorlijk vervelende en foutgevoelige standaardcode.

Java 8 Optioneel klasse kan helpen om situaties aan te pakken waarin er een mogelijkheid is om de NPE. Het werkt als een container voor het object van het type T. Het kan een waarde van dit object retourneren als deze waarde geen nul. Als de waarde in deze container nul het maakt het mogelijk om een ​​aantal vooraf gedefinieerde acties uit te voeren in plaats van te gooien NPE.

4.1. Oprichting van de Optioneel

Een exemplaar van de Optioneel klasse kan worden gemaakt met behulp van de statische methoden:

Optioneel optioneel = Optioneel.empty ();

Retourneert een leeg Optioneel.

String str = "waarde"; Optioneel optioneel = Optioneel.of (str);

Retourneert een Optioneel die een niet-nulwaarde bevat.

Optioneel optioneel = Optioneel.ofNullable (getString ());

Zal een Optioneel met een specifieke waarde of een lege Optioneel als de parameter is nul.

4.2. Optioneel gebruik

U verwacht bijvoorbeeld een Lijst en in het geval van nul u wilt het vervangen door een nieuw exemplaar van een ArrayList. W.ih de code van vóór Java 8 moet je zoiets als dit doen:

Lijst lijst = getList (); Lijst listOpt = lijst! = Null? lijst: nieuwe ArrayList ();

Met Java 8 kan dezelfde functionaliteit worden bereikt met een veel kortere code:

Lijst listOpt = getList (). OrElseGet (() -> nieuwe ArrayList ());

Er is zelfs meer standaardcode als je op de oude manier het veld van een object moet bereiken. Stel dat je een object van type hebt Gebruiker die een veld van type heeft Adres met een veld sboom van het type Draad. En om de een of andere reden moet u een waarde van de straat veld als er enkele bestaan ​​of een standaardwaarde als straat is nul:

Gebruiker user = getUser (); if (gebruiker! = null) {Adres adres = user.getAddress (); if (adres! = null) {String street = address.getStreet (); if (street! = null) {return street; }}} retourneer "niet gespecificeerd";

Dit kan worden vereenvoudigd met Optioneel:

Optioneel gebruiker = Optioneel.ofNullable (getUser ()); String resultaat = gebruiker .map (Gebruiker :: getAddress) .map (Adres :: getStreet) .orElse ("niet gespecificeerd");

In dit voorbeeld hebben we de kaart() methode om de resultaten van het aanroepen van de getAdress () naar de Optioneel en getStreet () naar Optioneel. Als een van deze methoden is geretourneerd nul de kaart() methode retourneert een lege Optioneel.

Stel je voor dat onze getters terugkeren Optioneel. Dus we moeten de flatMap () methode in plaats van de kaart():

Optioneel optionalUser = Optioneel.ofNullable (getOptionalUser ()); String resultaat = optionalUser .flatMap (OptionalUser :: getAddress) .flatMap (OptionalAddress :: getStreet) .orElse ("niet gespecificeerd");

Nog een use-case van Optioneel verandert NPE met nog een uitzondering. Laten we dus, zoals we eerder hebben gedaan, proberen dit te doen in de stijl van vóór Java 8:

Stringwaarde = null; String resultaat = ""; probeer {resultaat = waarde.toUpperCase (); } catch (uitzondering NullPointerException) {throw new CustomException (); }

En wat als we gebruiken Optioneel? Het antwoord is beter leesbaar en eenvoudiger:

Stringwaarde = null; Optionele waardeOpt = Optioneel.ofNullable (waarde); String resultaat = waardeOpt.orElseThrow (CustomException :: nieuw) .toUpperCase ();

Merk op dat hoe en met welk doel te gebruiken Optioneel in uw app is een serieuze en controversiële ontwerpbeslissing, en uitleg van alle voor- en nadelen ervan valt buiten het bestek van dit artikel. Als u geïnteresseerd bent, kunt u dieper graven, er zijn tal van interessante artikelen op internet gewijd aan dit probleem. Deze en deze kunnen erg nuttig zijn.

5. Conclusie

In dit artikel bespreken we kort enkele interessante nieuwe functies in Java 8.

Er zijn natuurlijk vele andere toevoegingen en verbeteringen die verspreid zijn over vele Java 8 JDK-pakketten en klassen.

Maar de informatie die in dit artikel wordt geïllustreerd, is een goed startpunt voor het verkennen van en leren over enkele van deze nieuwe functies.

Ten slotte is alle broncode voor het artikel beschikbaar op GitHub.