05 sep 2024 Java 21 in een notendop Nieuws In deze blog vertelt onze docent Marko Draisma over Java 21. Hij geeft een panoramisch uitzicht op sleutelfuncties, inclusief taalverbeteringen, bibliotheekupdates en nog veel meer. Klopt! Of je nu een beginner bent die gretig is om te verkennen of een ervaren ontwikkelaar die klaar is om de nieuwste tools te benutten, Java 21 belooft iets spannends voor iedereen. Laten we enkele belangrijke ontwikkelingen onder de loep nemen, geïllustreerd door eenvoudige voorbeelden. Taalverbeteringen Pattern Matching voor switch (JEP 441) Java 21 introduceert een elegante verbetering van de switch-statement en expressie: Pattern Matching. Deze functie geeft een nieuwe dimensie aan hoe we omgaan met complexe data, waardoor code leesbaarder, flexibeler en minder foutgevoelig wordt. Het is een sprong voorwaarts in het verminderen van boilerplate code, omdat het de noodzaak voor handmatige typecontroles en casting elimineert. Toepassing Stel je een scenario voor in een grafische applicatie die verschillende vormen behandelt. Elke vorm (Circle, Rectangle, Square) heeft unieke eigenschappen. Traditioneel vereiste het omgaan met zo’n diversiteit omslachtige if-else constructies of een switch met expliciete typecontroles. Pattern Matching voor switch stroomlijnt dit proces. Voorbeeld sealed interface Shape permits Circle, Rectangle, Square { } record Circle(double radius) implements Shape { } record Rectangle(double length, double width) implements Shape { } record Square(double side) implements Shape { } public static String shapeDetails(Shape shape) { return switch (shape) { case Circle c -> “Cirkel met straal: “ + c.radius(); case Rectangle r -> “Rechthoek met afmetingen: “ + r.length() + “x” + r.width(); case Square s -> “Vierkant met zijde: “ + s.side(); default -> “Onbekende vorm”; }; } Record Patterns (JEP 440) Voortbouwend op de basis van Pattern Matching, stellen Record Patterns je in staat om recordwaarden te deconstrueren binnen patronen. Deze relatie tussen Record Patterns en Pattern Matching voor switch verhoogt de leesbaarheid en efficiëntie van code bij het gebruik van gestructureerde data. Toepassing Voortbordurend op het voorbeeld van de grafische applicatie, wordt in de volgende code de oppervlakte van vormen binnen een switch-expressie berekend. Record Patterns faciliteren een elegante en directe benadering. Voorbeeld public static double computeArea(Shape shape) { return switch (shape) { case Circle(double radius) -> Math.PI * radius * radius; case Rectangle(double length, double width) -> length * width; case Square(double side) -> side * side; default -> 0; }; } Merk op dat in elke case een record type genoemd wordt, inclusief de parameters (de record components), zodat deze components rechtstreeks gebruikt kunnen worden achter de pijl. Bibliotheekverbeteringen Virtual Threads (JEP 444) Virtual Threads zijn een game-changer voor concurrency in Java, die een lichtgewicht en schaalbaar alternatief bieden voor traditionele threads. Deze functie maakt het beheer van miljoenen gelijktijdige taken mogelijk met minimale overhead, wat een significante verschuiving markeert in hoe ontwikkelaars gelijktijdige programmering in Java benaderen. Toepassing Stel je een serverapplicatie voor die duizenden verbindingen tegelijkertijd beheert. Traditionele threads worstelen om dergelijke I/O-gebonden taken efficiënt aan te pakken vanwege hun significante overhead. JDK threads zijn namelijk een wrapper rondom platform threads van het OS, waarvan je er in de meeste gevallen maximaal enkele duizenden tegelijk kunt hebben draaien. Virtual Threads revolutioneren dit scenario, waarbij elke verbinding kan worden beheerd door zijn eigen thread, waardoor het verbruik van bronnen drastisch wordt verminderd en de schaalbaarheid wordt verbeterd. Voorbeeld import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class EchoServer { public static void start(int port) throws IOException { try (ServerSocket serverSocket = new ServerSocket(port)) { while (true) { Socket clientSocket = serverSocket.accept(); Thread.startVirtualThread(() -> handleClient(clientSocket)); } } } private static void handleClient(Socket clientSocket) { // Implementatie van clientbehandeling System.out.println(“Client behandeld door virtuele thread: “ + Thread.currentThread().getName()); } } Een virtual thread draait, net als een traditionele thread, op een platform thread, maar is niet voor de gehele levensduur van dezelfde platform thread afhankelijk. In dit voorbeeld, als in de handleClient method gewacht moet worden, bijvoorbeeld op het verkrijgen van een database connectie, dan zal de virtual thread z’n platform thread loslaten. Zodra de virtual thread weer wat te doen heeft, zal een (mogelijk andere) platform thread gebruikt kunnen worden voor het vervolg. Dit gebeurt op een geheel transparante manier: de applicatie code leeft in één virtual thread. Collecties Sequenced Collections (JEP 431) Java 21 introduceert Sequenced Collections, die een uniforme manier bieden om met geordende verzamelingen van elementen te werken. Dit omvat SequencedCollection, SequencedSet, en SequencedMap. Specifiek biedt SequencedCollection methoden zoals addFirst, addLast, getFirst, getLast, removeFirst, removeLast, en reversed, die ontwikkelaars meer controle geven over hoe elementen worden beheerd in termen van volgorde. Voorbeeld: een Toddo-lijst Stel je een toepassing voor die een ToDo-lijst beheert waarbij de volgorde van taken belangrijk is, en je wilt gemakkelijk taken aan het begin of het einde van de lijst kunnen toevoegen, de eerste of laatste taak kunnen ophalen, en taken van zowel het begin als het einde van de lijst kunnen verwijderen. Hier is hoe je SequencedCollection zou kunnen gebruiken in zo’n scenario: import java.util.LinkedList; import java.util.SequencedCollection; public class ToDoListManager { public static void main(String[] args) { SequencedCollection<String> toDoList = new LinkedList<>(); // Taken toevoegen toDoList.addLast(“Koffie zetten”); toDoList.addLast(“E-mails beantwoorden”); toDoList.addFirst(“Dagplanning maken”); // Eerste en laatste taken weergeven System.out.println(“Eerste taak: “ + toDoList.getFirst()); System.out.println(“Laatste taak: “ + toDoList.getLast()); // Eerste en laatste taken verwijderen toDoList.removeFirst(); toDoList.removeLast(); // Overgebleven taken weergeven System.out.println(“Overgebleven taken in de lijst:”); toDoList.forEach(System.out::println); // De lijst omkeren SequencedCollection<String> reversedList = toDoList.reversed(); System.out.println(“Omgekeerde lijst van taken:”); reversedList.forEach(System.out::println); } } In dit voorbeeld gebruiken we LinkedList, een concrete implementatie van SequencedCollection, om de diverse methoden te demonstreren die het beheer van een geordende lijst van taken vergemakkelijken. Door methoden zoals addFirst, addLast, en removeFirst, removeLast te gebruiken, kunnen we flexibel bepalen hoe en waar taken worden toegevoegd of verwijderd in de lijst. De getFirst en getLast methoden bieden snelle toegang tot respectievelijk de eerste en laatste taak, terwijl de reversed methode een omgekeerde weergave van de lijst biedt, wat handig kan zijn voor bepaalde gebruiksscenario’s. Meer weten? Volg dan deze cursus: Java 21 Programming Language – deel 1. Dit is een vijfdaagse cursus waarin je de basis leert in het object georiënteerd programmeren met Java. Denk hierbij aan het werken met classes en objecten, het werken met interfaces, foutafhandeling, functioneel programmeren met behulp van lambda expressies en meer. De cursus Java 21 Programming Language – deel 2 is voor de ervaren Java programmeur die zich meer wil verdiepen in specifieke toepassingsgebieden. We behandelen in vijf dagen onderwerpen als concurrency, input/output, records, sealed classes en localization. Samen bereiden deze cursussen je voor op een Oracle Certified Professional (OCP) certificering. Vijfhart, dat klopt voor jou! Gerelateerde artikelen Microsoft 365 Copilot: verbeteringen en uitbreiding met pages Git: tijdmachine voor al je code o1: OpenAI’s denkende revolutie