Java >> Java tutorial >  >> Tag >> new

Nye funktioner i Java 16

1. Oversigt

Java 16, udgivet den 16. marts 2021, er den seneste kortsigtede inkrementelle udgivelse, der bygger på Java 15. Denne udgivelse kommer med nogle interessante funktioner, såsom optegnelser og forseglede klasser.

I denne artikel vil vi udforske nogle af disse nye funktioner.

2. Påkald standardmetoder fra proxy-instanser (JDK-8159746)

Som en forbedring af standardmetoden i Interfaces er der med udgivelsen af ​​Java 16 tilføjet support til java.lang.reflect.InvocationHandler påberåbe standardmetoder for en grænseflade via en dynamisk proxy ved hjælp af refleksion.

For at illustrere dette, lad os se på et simpelt eksempel på en standardmetode:

interface HelloWorld {
    default String hello() {
        return "world";
    }
}

Med denne forbedring kan vi påberåbe standardmetoden på en proxy for denne grænseflade ved hjælp af refleksion:

Object proxy = Proxy.newProxyInstance(getSystemClassLoader(), new Class<?>[] { HelloWorld.class },
    (prox, method, args) -> {
        if (method.isDefault()) {
            return InvocationHandler.invokeDefault(prox, method, args);
        }
        // ...
    }
);
Method method = proxy.getClass().getMethod("hello");
assertThat(method.invoke(proxy)).isEqualTo("world");

3. Dagsperiodesupport (JDK-8247781)

En ny tilføjelse til DateTimeFormatter er periode-på-dagen-symbolet "B “, som giver et alternativ til am/pm-formatet:

LocalTime date = LocalTime.parse("15:25:08.690791");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("h B");
assertThat(date.format(formatter)).isEqualTo("3 in the afternoon");

I stedet for noget som "15:00 “, får vi et output på “3 om eftermiddagen “. Vi kan også bruge "B “, “BBBB “ eller “BBBBBDateTimeFormatter mønster til henholdsvis korte, fyldige og smalle stilarter.

4. Tilføj Stream.toList Metode (JDK-8180352)

Målet er at reducere kedelpladen med nogle almindeligt anvendte Stream samlere, såsom Collectors.toList og Collectors.toSet :

List<String> integersAsString = Arrays.asList("1", "2", "3");
List<Integer> ints = integersAsString.stream().map(Integer::parseInt).collect(Collectors.toList());
List<Integer> intsEquivalent = integersAsString.stream().map(Integer::parseInt).toList();

Vores hensigter eksempel fungerer på den gamle måde, men intsEquivalent har samme resultat og er mere kortfattet.

5. Vector API Incubator (JEP-338)

Vector API'et er i sin indledende inkubationsfase for Java 16. Ideen med denne API er at give et middel til vektorberegninger, der i sidste ende vil være i stand til at yde mere optimalt (ved at understøtte CPU-arkitekturer) end den traditionelle skalære beregningsmetode.

Lad os se på, hvordan vi traditionelt kan multiplicere to arrays:

int[] a = {1, 2, 3, 4};
int[] b = {5, 6, 7, 8};

var c = new int[a.length];

for (int i = 0; i < a.length; i++) {
    c[i] = a[i] * b[i];
}

Dette eksempel på en skalær beregning vil, for en matrix med længde 4, udføres i 4 cyklusser. Lad os nu se på den tilsvarende vektorbaserede beregning:

int[] a = {1, 2, 3, 4};
int[] b = {5, 6, 7, 8};

var vectorA = IntVector.fromArray(IntVector.SPECIES_128, a, 0);
var vectorB = IntVector.fromArray(IntVector.SPECIES_128, b, 0);
var vectorC = vectorA.mul(vectorB);
vectorC.intoArray(c, 0);

Det første, vi gør i den vektorbaserede kode, er at oprette to IntVectors  fra vores input-arrays ved hjælp af den statiske fabriksmetode for denne klasse fromArray. Den første parameter er størrelsen af ​​vektoren, efterfulgt af arrayet og offset (her sat til 0). Det vigtigste her er størrelsen af ​​vektoren, som vi får til 128 bit. I Java, hver int tager 4 bytes at holde.

Da vi har et input-array på 4 ints, det tager 128 bit at gemme. Vores single Vector kan gemme hele arrayet.

På visse arkitekturer vil compileren være i stand til at optimere bytekoden for at reducere beregningen fra 4 til kun 1 cyklus. Disse optimeringer gavner områder som maskinlæring og kryptografi.

Vi bør bemærke, at det at være i inkubationsstadiet betyder, at denne Vector API kan ændres med nyere udgivelser.

6. Optegnelser (JEP-395)

Records blev introduceret i Java 14. Java 16 bringer nogle trinvise ændringer.

Optegnelser ligner enum s i det faktum, at de er en begrænset form for klasse. Definition af en post er en kortfattet måde at definere et uforanderligt dataholdende objekt på.

6.1. Eksempel uden registreringer

Lad os først definere en bog klasse:

public final class Book {
    private final String title;
    private final String author;
    private final String isbn;

    public Book(String title, String author, String isbn) {
        this.title = title;
        this.author = author;
        this.isbn = isbn;
    }

    public String getTitle() {
        return title;
    }

    public String getAuthor() {
        return author;
    }

    public String getIsbn() {
        return isbn;
    }

    @Override
    public boolean equals(Object o) {
        // ...
    }

    @Override
    public int hashCode() {
        return Objects.hash(title, author, isbn);
    }
}

Oprettelse af simple dataholdeklasser i Java kræver en masse kedelkode. Dette kan være besværligt og føre til fejl, hvor udviklere ikke leverer alle de nødvendige metoder, såsom lig med og hashCode .

På samme måde springer udviklere nogle gange over de nødvendige trin for at skabe korrekte uforanderlige klasser. Nogle gange ender vi med at genbruge en klasse til generelle formål i stedet for at definere en specialist for hver brugssag.

De fleste moderne IDE'er giver mulighed for autogenerering af kode (såsom sættere, gettere, konstruktører osv.), der hjælper med at afbøde disse problemer og reducerer omkostningerne på en udvikler, der skriver koden. Records giver dog en indbygget mekanisme til at reducere kedelkoden og skabe det samme resultat.

6.2. Eksempel med Records

Her er bog genskrevet som en Record :

public record Book(String title, String author, String isbn) {
}

Ved at bruge posten søgeord, har vi reduceret bogen klasse til to linjer. Dette gør det meget nemmere og mindre udsat for fejl.

6.3. Nye tilføjelser til poster i Java 16

Med udgivelsen af ​​Java 16 kan vi nu definere poster som klassemedlemmer af indre klasser. Dette skyldes afslappende begrænsninger, der blev overset som en del af den trinvise udgivelse af Java 15 under JEP-384:

class OuterClass {
    class InnerClass {
        Book book = new Book("Title", "author", "isbn");
    }
}

7. Mønstermatching for instanceof (JEP-394)

Mønstermatching for instansen af nøgleord er blevet tilføjet fra Java 16.

Tidligere kunne vi skrive kode som denne:

Object obj = "TEST";

if (obj instanceof String) {
    String t = (String) obj;
    // do some logic...
}

I stedet for udelukkende at fokusere på den logik, der er nødvendig for applikationen, skal denne kode først kontrollere forekomsten af ​​obj , cast derefter objektet til en streng og tildel den til en ny variabelt.

Med introduktionen af ​​mønstermatchning kan vi omskrive denne kode:

Object obj = "TEST";

if (obj instanceof String t) {
    // do some logic
}

Vi kan nu erklære en variabel – i dette tilfælde t – som en del af instansen af tjek.

8. Forseglede klasser (JEP-397)

Forseglede klasser, der først blev introduceret i Java 15, giver en mekanisme til at bestemme, hvilke underklasser der har tilladelse til at udvide eller implementere en overordnet klasse eller grænseflade.

8.1. Eksempel

Lad os illustrere dette ved at definere en grænseflade og to implementeringsklasser:

public sealed interface JungleAnimal permits Monkey, Snake  {
}

public final class Monkey implements JungleAnimal {
}

public non-sealed class Snake implements JungleAnimal {
}

De forseglede søgeord bruges sammen med tilladelserne nøgleord for at bestemme præcis, hvilke klasser der har tilladelse til at implementere denne grænseflade. I vores eksempel er dette Abe og Slange.

Alle nedarvede klasser af en forseglet klasse skal markeres med en af ​​følgende:

  • forseglet – hvilket betyder, at de skal definere, hvilke klasser der har tilladelse til at arve fra det ved hjælp af tilladelserne søgeord.
  • endelig – forhindrer yderligere underklasser
  • ikke-forseglet – giver enhver klasse mulighed for at arve fra den.

En væsentlig fordel ved forseglede klasser er, at de giver mulighed for udtømmende mønstertilpasningskontrol uden behov for en fangst for alle ikke-dækkede tilfælde. For eksempel, ved at bruge vores definerede klasser, kan vi have logik til at dække alle mulige underklasser af JungleAnimal :

JungleAnimal j = // some JungleAnimal instance

if (j instanceof Monkey m) {
    // do logic
} else if (j instanceof Snake s) {
    // do logic
}

Vi har ikke brug for et andet blok, da de forseglede klasser kun tillader de to mulige undertyper af Abe og Slange .

8.2. Nye tilføjelser til forseglede klasser i Java 16

Der er et par tilføjelser til forseglede klasser i Java 16. Dette er de ændringer, som Java 16 introducerer til den forseglede klasse:

  • Java-sproget genkender forseglet , ikke-forseglet og tilladelser som kontekstuelle søgeord (svarende til abstrakt og forlænger )
  • Begræns muligheden for at oprette lokale klasser, der er underklasser af en forseglet klasse (svarende til manglende evne til at oprette anonyme klasser af forseglede klasser).
  • Strengere kontrol ved støbning af forseglede klasser og klasser afledt af forseglede klasser

9. Andre ændringer

I forlængelse af JEP-383 i Java 15-udgivelsen giver den fremmede linker API en fleksibel måde at få adgang til indbygget kode på værtsmaskinen. I første omgang, for C-sprog interoperabilitet, kan det i fremtiden være tilpasset til andre sprog såsom C++ eller Fortran. Målet med denne funktion er til sidst at erstatte Java Native Interface.

En anden vigtig ændring er, at JDK internals nu er stærkt indkapslet som standard. Disse har været tilgængelige siden Java 9. Men nu kræver JVM argumentet –illegal-access=permit . Dette vil påvirke alle biblioteker og apps (især når det kommer til test), der i øjeblikket bruger JDK internals direkte og blot ignorerer advarselsmeddelelserne.

10. Konklusion

I denne artikel dækkede vi nogle af de funktioner og ændringer, der blev introduceret som en del af den inkrementelle Java 16-udgivelse. Den komplette liste over ændringer i Java 16 er i JDK release notes.

Som altid kan al koden i dette indlæg findes på GitHub.


Java tag