1+ package pl .mperor .lab .java ;
2+
3+ import org .junit .jupiter .api .Assertions ;
4+ import org .junit .jupiter .api .Test ;
5+ import pl .mperor .lab .TestUtils ;
6+
7+ import java .util .Collections ;
8+ import java .util .List ;
9+ import java .util .NoSuchElementException ;
10+ import java .util .SequencedCollection ;
11+
12+ /// Java 21™ (September 2023)
13+ /// [JDK 21](https://openjdk.org/projects/jdk/21)
14+ ///
15+ /// - STANDARD FEATURES:
16+ /// - 444: Virtual Threads
17+ /// - 431: Sequenced Collections
18+ /// - 440: Record Patterns
19+ /// - 441: Pattern Matching for switch
20+ /// - 452: Key Encapsulation Mechanism API
21+ /// - 439: Generational ZGC
22+ /// - 451: Prepare to Disallow the Dynamic Loading of Agents
23+ /// - 449: Deprecate the Windows 32-bit x86 Port for Removal
24+ ///
25+ /// - PREVIEW & INCUBATOR:
26+ /// - 430: String Templates (Preview)
27+ /// - 442: Foreign Function & Memory API (Third Preview)
28+ /// - 443: Unnamed Patterns and Variables (Preview)
29+ /// - 445: Unnamed Classes and Instance Main Methods (Preview)
30+ /// - 446: Scoped Values (Preview)
31+ /// - 453: Structured Concurrency (Preview)
32+ /// - 448: Vector API (Sixth Incubator)
33+ public class Java21 {
34+
35+ @ Test
36+ public void testVirtualThreads () throws InterruptedException {
37+ TestUtils .ReadableOut out = TestUtils .setTempSystemOut ();
38+ Thread virtualThread = Thread .startVirtualThread (() ->
39+ System .out .print ("Hello from Virtual Thread!" )
40+ );
41+ virtualThread .join ();
42+ TestUtils .resetSystemOut ();
43+
44+ Assertions .assertTrue (virtualThread .isDaemon () && virtualThread .isVirtual ());
45+ Assertions .assertEquals (Thread .NORM_PRIORITY , virtualThread .getPriority ());
46+ Assertions .assertEquals ("Hello from Virtual Thread!" , out .all ());
47+ }
48+
49+ @ Test
50+ public void testSequencedCollections () {
51+ List <String > letters = List .of ("one" , "two" , "three" );
52+ Assertions .assertInstanceOf (SequencedCollection .class , letters );
53+ Assertions .assertEquals ("one" , letters .getFirst ());
54+ Assertions .assertEquals ("three" , letters .getLast ());
55+ Assertions .assertThrows (NoSuchElementException .class , Collections .emptyList ()::getFirst );
56+ }
57+
58+ @ Test
59+ public void testRecordPatternDeconstruct () {
60+ record Point (int x , int y ) {}
61+ record LineSegment (Point start , Point end ) {}
62+ Object obj = new LineSegment (new Point (0 , 1 ), new Point (1 , 2 ));
63+
64+ if (obj instanceof LineSegment (Point (int x , int y ), Point end )) {
65+ Assertions .assertEquals (0 , x );
66+ Assertions .assertEquals (1 , y );
67+ Assertions .assertEquals (new Point (1 , 2 ), end );
68+ }
69+ }
70+
71+ @ Test
72+ public void testSwitchPatternMatching () {
73+ Assertions .assertEquals ("String: Hello" , switchOverClasses ("Hello" ));
74+ Assertions .assertEquals ("int: 1" , switchOverClasses (1 ));
75+ Assertions .assertEquals ("long: 13" , switchOverClasses (13L ));
76+ Assertions .assertEquals ("boolean: true" , switchOverClasses (true ));
77+ Assertions .assertEquals ("null" , switchOverClasses (null ));
78+ record Person (String name , String surname ) {
79+ @ Override
80+ public String toString () {
81+ return "%s %s" .formatted (name , surname );
82+ }
83+ }
84+ Assertions .assertEquals ("Object: John Doe" , switchOverClasses (new Person ("John" , "Doe" )));
85+ }
86+
87+ private static String switchOverClasses (Object obj ) {
88+ return switch (obj ) {
89+ case String s -> String .format ("String: %s" , s );
90+ case Integer i -> String .format ("int: %d" , i );
91+ case Long l -> String .format ("long: %d" , l );
92+ case Boolean b -> String .format ("boolean: %s" , b );
93+ case null -> "null" ;
94+ default -> "Object: " + obj ;
95+ };
96+ }
97+
98+ }
0 commit comments