Poster til tiden: Her er nyhederne i Java 14

Illustration: Bigstock/kentoh
Records, pattern matching og masser af andre nyheder i vinterens Java-udgave.

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.

Tips og korrekturforslag til denne historie sendes til tip@version2.dk
Følg forløbet
Kommentarer (10)
sortSortér kommentarer
  • Ældste først
  • Nyeste først
  • Bedste først
#1 Peter Jensen

Er Java ikke uhyggelig usikker og ikke noget der bør komme i nærheden af en Pc? Mange afinstallerer det og det truer også Mac. Så er der den Java applet til nemid. Java er et programmeringsprog og den runtime version der ligger på en Pc må være den der er usikker og svenskerne vil ikke bruge nemid login løsningen. Hvis nogen tror jeg blander begreberne så har de sikkert ret.

  • 1
  • 9
#2 Torben Mogensen Blogger

"Over time all languages evolve to look more and more like Standard ML".

Både pattern matching og records har eksisteret i mere elegante udgaver i SML i flere årtier, ditto i Haskell og OCaml (som begge har hentet inspiration i ML) og senere også i F# (som primært er inspireret af OCaml). Mange tidligere Javaudvidelser, blandt andet generics og anonyme funcktioner, er også hentet fra funktionssprog. Nu mangler vi bare:

  • Typeinferens.
  • At referencer ikke (per default) kan være null.
  • At variable ikke (per default) er muterbare.
  • Anonyme tupler (altså at kunne skrive ("x", 4) uden at erklære en partype først).
  • Pattern matching med indlejrede mønstre, alså ikke kun på den øverste konstruktor.
  • Funktorer.
  • Typeklasser.
  • En mere elegant sumtypekonstruktion.
  • En mere elegant (mindre ordrig) syntaks.

Så begynder Java måske at være brugbart. :-)

  • 5
  • 1
#4 Palle Due Larsen

Er Java ikke uhyggelig usikker og ikke noget der bør komme i nærheden af en pc?

Du tænker på Java-applets, som er en død teknologi. Applets var beregnet til at kode på en hjemmeside kunne afvikles i din browser. De plugins, der skulle til var usikre og krævede mange opdateringer. Den rolle er overtaget af Javascript, som Christian Nobel skriver ovenover.

Java som programmeringssprog og afviklingsmiljø bruges i stor stil i bank- og forsikringsverdenen og er ikke mindre sikker end tilsvarende teknologier. Hvis du ikke programmerer, er der næppe nogen grund til, at du skal have Java installeret idag.

  • 7
  • 0
#5 Joe Sørensen

Ja, problemet var hele ideen med at have browser plugins. Den kører andres programmer på din computer, i en fortolker, der har adgang til resourcer, der ligger uden for browseren.

Kald det Flash, Silverlight eller endda ActiveX.

Det var ellers lidt cool, at man kunne installere drivere i styresystemet via browser plugins. Der har endda eksisteret hjemmesider, som downloaded i iso image til browserens cache og derefter bootede Linux maskinen derfra. Det blev desværre ødelagt at Windows XP SP2 opdateringen, men stadig cool.

  • 2
  • 0
#6 Peter Jensen

Jeg havde skrevet javapplets i stedet for javascript - min fejl. Sidste gang jeg programmerede var i 1993 i turbopascal og før det var det i assembler, så jeg kunne fylde en eprom med et program der kunne styre en Z80 processor. Siden har jeg ikke programmeret fordi jeg ikke har haft brug for det på grund af et brancheskift.

Tak for alle indsparkene.

Peter

  • 2
  • 1
#10 Nis Schmidt

Nogle mener åbanbart, at jo mere et sprog kommer til at ligne det sprog de selv lærte før "yngre stenalder," jo bedre - men som bekendt sluttede stenalderen ikke pga mangel på sten!

Jo jo, da man kan altid ønske sig mere "syntaktisk sukker", mere som andet sukkerstads og mættet fedt "clutter" det bare level-1 cachen til instruktioner. Til sidst er emulator-gevinsten væk, Moores lov retired - uden afløser og optimerende compilere kan alligevel ikke "læse" programmørens tanker. Når det om føje tid kan erkendes, vil flere nok lytte til MIT-professoren Charles E Leiserson og (farvel bargaining chip) hans undergraduate kursus 6.172 på ocw.mit.edu

you just can't win

ref: https://www.youtube.com/watch?v=U1p5_Kg9YGU

  • 0
  • 4
Log ind eller Opret konto for at kommentere