Timeline 6 Java official ‘birthday’ Java SE 1.2.2 + Java EE 1.2 ”kings” of enterprise software ‘Legacy’ Java maturity Generics Annotations Auto(un)boxing Lambdas Probably, the most used release of all time LTS at least up to 2030 (Eclipse Temurin) Modules JShell Continuous innovation Early community involvement and feedback (incubators, previews) https://javaalmanac.io/jdk/ || https://versionlog.com/java/
for the unwary Java developer 6 MONTH release cycle (March & September) LTS release every 2 YEARS Latest release is Java 26 Previous LTS is Java 21 Current LTS is Java 25 NEXT LTS will be JAVA 29 (09/27) 7
for the unwary Java developer Java is FREE and open source Code is hosted and developed at GitHub: https://github.com/openjdk/jdk MANY DISTRIBUTIONS of the JDK packages and others 8
for the unwary Java developer Java runs just-in-time (JIT) Java runs ahead-of-time (AOT) Java runs from bytecodes and from native images Project Leyden 9
switch & switch expressions before int days = 0; switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: days = 31; break; case 4: case 6: case 9: days = 30; break; case 2: days = 28; break; default: throw new IllegalArgumentException("Invalid month"); } 12
text blocks before var dbQuery = """ CREATE TABLE 'TEST'.'EMPLOYEE' ( 'ID' INT NOT NULL DEFAULT 0, 'FIRST_NAME' VARCHAR(100) NOT NULL, 'LAST_NAME' VARCHAR(100) NULL, 'STAT_CD' TINYINT NOT NULL DEFAULT 0 ); """; System.out.println(dbQuery); 14
16 after record AuditInfo( LocalDateTime createdOn, String createdBy, LocalDateTime updatedOn, String updatedBy) { } how to use a Record var myAudit = new AuditInfo( LocalDateTime.now().minusHours(1), "jorge", LocalDateTime.now(), "julio"); System.out.println(myAudit.updatedBy());
matching for instanceof 19 even better interface Shape { static double getPerimeter(Shape shape) throws IllegalArgumentException { ... } else if (shape instanceof Circle c && c.radius() == 0) { throw new IllegalArgumentException( "A circle with 0 radius is a point"); ... } } }
refresh – Java 17 and Java 18 20 Java 17 Sealed classes (final) Vector API (2nd incubator) Pattern matching for switch (preview) Foreign function and memory API (incubator) Apple AArch64 (macOS) port Removal of Applet API Java 18 Vector API (3rd incubator) Pattern matching for switch (2nd preview) Foreign function and memory API (2nd incubator) Simple Web Server UTF-8 as default charset Code snippets in Javadocs Deprecation of finalization Java 17 is, probably, where most of you are working nowadays
threads 23 before 1 java.lang.Thread = 1 OS Thread after 1 java.lang.Thread = 1 virtual Thread JVM OS ← these are limited and can be exhausted easily JVM VT OS ← OS threads are more wisely used e.g., shared by multiple virtual threads
matching for switch 26 use types as input for switch blocks supports null supports using records supports conditional logic with keyword when interface Shape {} record Rectangle(double length, double width) implements Shape {} record Circle(double radius) implements Shape {}
matching for switch 27 static double getPerimeter(Shape shape) throws IllegalArgumentException { return switch (shape) { case null -> throw new IllegalArgumentException( "Null reference not allowed"); case Rectangle r -> 2 * r.length() + 2 * r.width(); case Circle c -> 2 * c.radius() * Math.PI; default -> throw new IllegalArgumentException( "Unrecognized shape"); }; } var r1 = new Rectangle(2, 5); var c1 = new Circle(8); getPerimeter(r1); getPerimeter(c1); getPerimeter(null);
matching for switch 28 static void describeShape(Shape shape) throws IllegalArgumentException { switch (shape) { case null -> throw new IllegalArgumentException( "Null reference not allowed"); case Rectangle r when (r.length() > 100 || r.width() > 100) -> System.out.println("it’s huge! (%.1f, %.1f)". formatted(r.length(), r.width())); case Rectangle r -> System.out.println("normal rectangle"); case Circle c -> System.out.println("a circle"); default -> throw new IllegalArgumentException( "Unrecognized shape"); }; } describeShape(r1); describeShape(c1); var r2 = new Rectangle(150, 110); describeShape(r2);
patterns 29 extends pattern matching for instanceof to records allows for record deconstruction record Point(int x, int y) {} enum Color { RED, GREEN, BLUE } record ColoredPoint(Point p, Color c) {} record ColoredRectangle(ColoredPoint upperLeft, ColoredPoint lowerRight) implements Shape {} static void describeColoredShape(Shape s) { if (s instanceof ColoredRectangle cr) { System.out.println("a colored rectangle"); System.out.println("upper left corner x = " + cr.upperLeft().p().x()); } }
patterns 30 alternate way static void describeColoredShape(Shape s) { if (s instanceof ColoredRectangle( ColoredPoint(Point(var x1, var y1), var c1), ColoredPoint(Point(var x2, var y2), var c2))) { System.out.println("a colored rectangle"); System.out.println("upper left corner x = " + x1); } } var cr = new ColoredRectangle( new ColoredPoint(new Point(2, 5), Color.RED), new ColoredPoint(new Point(15, 12), Color.BLUE)); describeColoredShape(cr);
patterns 31 also works within switch blocks also works in conditionals static void describeShape(Shape shape) throws IllegalArgumentException { switch (shape) { case null -> throw new IllegalArgumentException( "Null reference not allowed"); case Rectangle(var l, var w) when (l > 100 || w > 100) -> System.out.println("it’s huge! (%.1f, %.1f)". formatted(l, w)); case Rectangle r -> System.out.println("normal rectangle"); case Circle c -> System.out.println("a circle"); default -> throw new IllegalArgumentException( "Unrecognized shape"); }; } describeShape(r2);
variables & patterns 32 anywhere a value does not need to be referred makes it clear that a value is intentionally unused static void describeColoredShape(Shape s) { if (s instanceof ColoredRectangle( ColoredPoint(Point(var x1, var _), var _), var _)) { System.out.println("a colored rectangle"); System.out.println("upper left corner x = " + x1); } } describeColoredShape(cr);
collections 34 with ‘classic’ Java <21 collections • access to first and last element is not consistent • iterating in natural sequence is consistent (iterators, for each) • iterating in inverted order is not consistent (even hard to achieve) Collection type First element Last element List l.get(0) l.get(l.size() - 1) Deque d.getFirst() d.getLast() SortedSet s.first() s.last() LinkedHashSet hs.iterator().next() no direct way
imports 39 reduce verbosity when importing multiple classes import module java.base; import module java.logging; import module java.sql; importing a module applies to all types exported directly or indirectly by that module (transitive dependencies) disambiguation is needed before using a symbol present in multiple modules import module java.base; import module java.desktop; import java.util.List; List l = ... https://openjdk.org/jeps/511
Source Files and Instance Main Methods 40 the “brand-new minimal Java program” void main() { IO.println("Hello World!"); } how to read this • Implicit new class in the default package named from the source file name • Implicit module import to java.base • Uses the new utility class java.lang.IO https://openjdk.org/jeps/512
Source Files and Instance Main Methods 41 another example void main() { String name = IO.readln("Please enter your name: "); IO.print("Pleased to meet you, "); IO.println(name); } $ java HelloWorld.java $ javac HelloWorld.java $ java HelloWorld https://openjdk.org/jeps/512
constructors 42 allows for certain logic before invoking super() convenient to check inputs and prepare values before the object is instantiated (no more half-ready objects) class A { A() { // A prologue super(); // A epilogue } } class B extends A { B() { // B prologue super(); // B epilogue } } https://openjdk.org/jeps/513 B prologue --> A prologue --> Object constructor body --> A epilogue B epilogue
constructors 43 allows for certain logic before invoking super() convenient to check inputs and prepare values before the object is instantiated (no more half-ready objects) class A { A() { IO.print("2"); // A prologue super(); IO.print("3"); // A epilogue } } class B extends A { B() { IO.print("1"); // B prologue super(); IO.print("4"); // B epilogue } } var b = new B() // prints: 1234 https://openjdk.org/jeps/513
new in Java 26 44 Java 26 Remove the Applet API Prepare to make final mean final Primitive types in patterns, instanceof and switch (4th preview) Structured concurrency (6th preview) Vector API (11th incubator) Lazy constants (2nd preview) – as stable values in Java 25 PEM encodings API (3rd preview) HTTP/3 for the HTTP Client API AOT object caching with any GC G1 GC improvements https://openjdk.org/projects/jdk/26/
expected for Java 27 (now in rampdown phase) 45 Java 27 Compact object headers by default Make G1 the default GC in all environments Post-quantum hybrid key exchange for TLS 1.3 Primitive types in patterns, instanceof and switch (5th preview) Structured concurrency (7th preview) Vector API (12th incubator) Lazy constants (3rd preview) PEM encodings API (4th preview) JFR in-process data redaction https://openjdk.org/projects/jdk/27/