Et nyt kode-år er skudt i gang, og dermed er det tid til en ny omgang Java, der som bekendt udrulles hver sjette måned.
Den nye version har nummeret 14, og til forskel fra de sidste par slanke versioner, er der et fyldigt udvalg af nyheder, og hele to nyskabelser i selve sproget. Faciliteterne i den nye udgave er fastfrosset, men api’er kan derimod godt skifte ham i de næste par måneder, inden den endelige version løber af stablen.
Først på listen er records, der ligner structs og records i alle mulige andre sprog, som C, Pascal og flere til.
Java var tilbage i tidernes morgen et lille sprog, hvor filosofien var, at klasse-begrebet skulle benyttes i forbindelse med alle sprogets faciliteter.
En gængs data-klasse ser derfor tit sådan ud:
public class Punkt { public final int x; public final int y; public Punkt(int x, int y) { this.x = x; this.y = y; } }
Altså en hel del linjer for at udtrykke, at vi vil skabe en klasse, der indeholder to heltals-koordinater for et punkt. Men ofte er det ikke slut her. Hvis klassen skal benyttes i collection-klasser, skal vi også implementere Object-metoderne equals og hashCode:
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Punkt other = (Punkt) obj; if (x != other.x) return false; if (y != other.y) return false; return true; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + x; result = prime * result + y; return result; }
En fornuftig streng-repræsentation er som regel også påkrævet, til eksempelvis test og logning:
@Override public String toString() { return "Punkt [x=" + x + ", y=" + y + "]"; }
Det endte med en frygtelig masse linjer for at udtrykke noget, der er ganske simpelt. Værktøjer kan klare arbejdet - koden herover er genereret af Eclipse - men det er ikke helt tilfredsstillende, skriver Javas top-arkitekt Brian Goetz i sin begrundelse:
»IDE'er hjælper med at skrive det meste af koden i en databærer-klasse, men gør ikke noget for at hjælpe læseren med at forstå designets intention om, at ‘jeg er en data-holder for x, y og z’ fra de snesevis af linjer med standardtekst. Det skal være lettere at skrive Java-kode, der modellerer enkle dataklasser - at skrive, læse og verificere som korrekt.«
Derfor records. Ligesom enums er en record blot en speciel slags klasse med lidt compiler-fikumdik nedenunder. Det kan være så enkelt som:
record Punkt(int x, int y) {}
Her er klassen eller recordens navn slået sammen med constructeren, og så er den klar til brug:
var punkt = new Punkt(-2, 3); System.out.println(punkt.x + ", " + punkt.y); System.out.println(punkt.toString()); System.out.println(punkt.hashCode());
En ny instans skabes ligesom alle andre klasser med new
og parametrene, som blev angivet i record-definitionen. Den har pr. automatik felter, som har samme navne som parametrene (og som er final, altså uforanderlige), og den har færdiglavede toString-, hashCode- og equals-metoder. En record er i sig selv final og kan således ikke nedarves.
En record kan også have en eksplicit constructor til for eksempel at tjekke parametrenes gyldighed samt helt almindelige metoder, som herunder:
record Interval(int lav, int høj) { public Interval { if (lav > høj) /* Her refereres der til de implicitte constructor-parametre. */ throw new IllegalArgumentException( String.format("(%d,%d)", lav, høj)); } public int længde() { return høj - lav; } }
Som det er kutyme i disse Java-tider, er records et såkaldt preview, hvor der skal compiles med dette flag for at udnytte faciliteten:
--enable-preview --release 14
Pattern matching
Pattern matching, der tester et objekts type, er en anden nyhed.
Det findes i mange sprog, såsom Haskell og C#, og på denne front har Java allerede instanceof
-operatoren. I Javas ungdom kunne en nybegynder i sproget godt få at vide, at brug af instanceof var et tegn på, at man ikke forstod objektorientering og polymorfi.
Men verden har ændret sig siden da.
»Næsten ethvert program inkluderer en slags logik, der kombinerer test, hvis et udtryk har en bestemt type eller struktur og derefter betinget udtrækker komponenter i dets tilstand til yderligere behandling,« skriver Brian Goetz, og fortsætter:
»I stedet for at anvende ad-hoc-løsninger mener vi, at det er tid for Java at omfavne pattern matching. Pattern matching tillader, at den ønskede 'form' af et objekt kan udtrykkes kort (mønsteret), og for forskellige udsagn og udtryk til at teste den 'form' op mod deres input (matching).«
Senere skal den nye facilitet bygges sammen med den nye switch-facilitet, der kom i Java 12, men indtil videre ser det sådan ud:
if (obj instanceof String s) { // kan bruge s her System.out.println("Fandt en streng: " + s); } else { // kan ikke bruge s her System.out.println("Fandt noget, som ikke er streng: " + obj); }
I betingelsen til if-sætningen kan angives en variabel af en bestemt type, her en String, og hvis betingelsen er opfyldt, kan variablen anvendes i if-kroppen, men ikke i else-kroppen. Rækkevidden for den bundne variabel - s
i eksemplet - afgøres ud fra sammenhængen, så i eksemplet
if (!(obj instanceof String s)) { … } else { .. s.contains(..) .. }
– er det else-blokken, hvor s
kan anvendes.
Ligesom med records er den nye sprogmulighed et preview, hvor det tidligere angivne flag altså skal anvendes ved kompilering.
Nemmere nullpointer-fejlmeddelelser
Java-udviklerne har flottet sig denne gang, for ud over de to sprognyheder er der meget andet i godteposen.
En herlig nyskabelse er bedre fejlmeddelelser ved NullPointerExceptions. Det er den klassiske drillenisse med :
a.b.c.i = 99;
– hvor der skal en del krumspring til for at afklare, hvilket element, der udløser fejlen. Men sådan vil det ikke være i fremtiden, hvor fejlmeddelelsen vil se sådan ud:
Exception in thread "main" java.lang.NullPointerException: Cannot assign field "i" because "a" is null at Prog.main(Prog.java:5)
Den tidligere nævnte switch-facilitet fra Java 12 er nu forfremmet fra preview til standard, så ingen flag er nødvendige for at anvende faciliteten.
I modsætning hertil skal Java 13’s ‘text blocks’ - streng-konstanter, der løber over flere linjer - lige have et vrid til og forbliver i preview i Java 14.
Et nyt Packaging Tool er et værktøj, der understøtter platformsspecifikke installations-pakker, såsom msi og exe på Windows, pkg og dmg på macOS, og deb og rpm på Linux.
I den lidt mere langhårede ende er byte buffere, som kan skrive til såkaldt ‘non-volatile memory’ (NVM), hvilket vil sige flash-ram og andre slags lagringsmekanismer, som både kan læses nogenlunde lige så hurtigt som RAM og gemmer data, også når der ikke er strøm på.
Også i denne boldgade er et api til tilgang af hukommelse udenfor JVM’ens heap, som eksempelvis det populære caching-bibliotek Memcached.
Der er ikke en Java-aftapning uden ændringer i garbage collectors, og denne gang er der virkelig gang i festen. En tidligere GC’er med navnet CMS smides på på porten, men til gengæld kommer den eksperimentelle GC ZGC nu til Windows og Mac.
ZGC prøver at løse nogle af de svære problemer med GC’er, og har som mål at skralde-indsamlingen aldrig tager mere end 10 millisekunder, og at pauserne ikke øges i takt med hukommelsesforbruget. Samtidig skal den også kunne håndtere heaps på op til flere terabytes.
Download kodeeksempler
Og så er der endda flere nyheder endnu. Dem kan man læse mere om på projektets hjemmeside.
Der er efterhånden mange producenter, der fremstiller open source-aftapninger af Java, og en oversigt kan findes på Wikipedia.
Eksemplerne i denne artikel kan downloades her og er compilet med build 30. Den færdige udgave af Java 14 er programsat til at udkomme d. 17. marts.

...men det er dyrt at lave god journalistik. Derfor beder vi dig overveje at tegne abonnement på Version2.
Digitaliseringen buldrer derudaf, og it-folkene tegner fremtidens Danmark. Derfor er det vigtigere end nogensinde med et kvalificeret bud på, hvordan it bedst kan være med til at udvikle det danske samfund og erhvervsliv.
Og der har aldrig været mere akut brug for en kritisk vagthund, der råber op, når der tages forkerte it-beslutninger.
Den rolle har Version2 indtaget siden 2006 - og det bliver vi ved med.