├── .github └── workflows │ ├── maven-publish.yml │ └── maven.yml ├── .gitignore ├── .idea ├── encodings.xml ├── misc.xml ├── sonarlint │ ├── issuestore │ │ ├── 1 │ │ │ └── e │ │ │ │ └── 1e5acdc91df03a2e9f85c23862cfae48d609b93a │ │ ├── 3 │ │ │ └── 9 │ │ │ │ └── 39f75cef49943e1bc8c7916eaa81c80652536dd7 │ │ ├── 7 │ │ │ └── 4 │ │ │ │ └── 746c35fcc923e7bbe07a6e1591eb777c6c0d28b0 │ │ ├── 8 │ │ │ ├── 8 │ │ │ │ └── 88263ce9c5d2a4540209b8e0b0d6cef230bb0f48 │ │ │ └── e │ │ │ │ └── 8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d │ │ ├── e │ │ │ └── 2 │ │ │ │ └── e23996953c6018604d314386faac3307ab1deff3 │ │ └── f │ │ │ └── 5 │ │ │ └── f54cb9ff57f15fcb82cf19733a6dfc11dd81f491 │ └── securityhotspotstore │ │ ├── 1 │ │ └── e │ │ │ └── 1e5acdc91df03a2e9f85c23862cfae48d609b93a │ │ ├── 3 │ │ └── 9 │ │ │ └── 39f75cef49943e1bc8c7916eaa81c80652536dd7 │ │ ├── 7 │ │ └── 4 │ │ │ └── 746c35fcc923e7bbe07a6e1591eb777c6c0d28b0 │ │ ├── 8 │ │ ├── 8 │ │ │ └── 88263ce9c5d2a4540209b8e0b0d6cef230bb0f48 │ │ └── e │ │ │ └── 8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d │ │ ├── e │ │ └── 2 │ │ │ └── e23996953c6018604d314386faac3307ab1deff3 │ │ └── f │ │ └── 5 │ │ └── f54cb9ff57f15fcb82cf19733a6dfc11dd81f491 ├── vcs.xml └── workspace.xml ├── README.md ├── pom.xml └── src └── main └── java └── org └── amch ├── InstanceMainMethodLauncher.java ├── RecordPattern.java ├── ScopedValueUsageTest.java ├── SequencedCollectionTest.java ├── StringTemplateSample.java ├── StringTemplateTest.java └── UnnamedClass.java /.github/workflows/maven-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a package using Maven and then publish it to GitHub packages when a release is created 2 | # For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path 3 | 4 | name: Maven Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: self-hosted 14 | permissions: 15 | contents: read 16 | packages: write 17 | 18 | steps: 19 | - uses: actions/checkout@v3 20 | - name: Set up JDK 11 21 | uses: actions/setup-java@v3 22 | with: 23 | java-version: '11' 24 | distribution: 'temurin' 25 | server-id: github # Value of the distributionManagement/repository/id field of the pom.xml 26 | settings-path: ${{ github.workspace }} # location for the settings.xml file 27 | 28 | - name: Build with Maven 29 | run: mvn -B package --file pom.xml 30 | 31 | - name: Publish to GitHub Packages Apache Maven 32 | run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml 33 | env: 34 | GITHUB_TOKEN: ${{ github.token }} 35 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Java CI with Maven 10 | 11 | on: 12 | push: 13 | branches: [ "master" ] 14 | pull_request: 15 | branches: [ "master" ] 16 | 17 | jobs: 18 | build: 19 | 20 | runs-on: self-hosted 21 | 22 | steps: 23 | - uses: actions/checkout@v3 24 | - name: Set up JDK 21 25 | uses: actions/setup-java@v3 26 | with: 27 | java-version: '21' 28 | distribution: 'temurin' 29 | cache: maven 30 | - name: Build with Maven 31 | run: mvn -B package --file pom.xml 32 | 33 | # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive 34 | #- name: Update dependency graph 35 | # uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | !**/src/main/**/target/ 4 | !**/src/test/**/target/ 5 | 6 | ### IntelliJ IDEA ### 7 | .idea/modules.xml 8 | .idea/jarRepositories.xml 9 | .idea/compiler.xml 10 | .idea/libraries/ 11 | *.iws 12 | *.iml 13 | *.ipr 14 | 15 | ### Eclipse ### 16 | .apt_generated 17 | .classpath 18 | .factorypath 19 | .project 20 | .settings 21 | .springBeans 22 | .sts4-cache 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | !**/src/main/**/build/ 32 | !**/src/test/**/build/ 33 | 34 | ### VS Code ### 35 | .vscode/ 36 | 37 | ### Mac OS ### 38 | .DS_Store -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/sonarlint/issuestore/1/e/1e5acdc91df03a2e9f85c23862cfae48d609b93a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achhibi/java21-new-features/064c440f4ec5c78b500f1f2152862de8df0639c9/.idea/sonarlint/issuestore/1/e/1e5acdc91df03a2e9f85c23862cfae48d609b93a -------------------------------------------------------------------------------- /.idea/sonarlint/issuestore/3/9/39f75cef49943e1bc8c7916eaa81c80652536dd7: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achhibi/java21-new-features/064c440f4ec5c78b500f1f2152862de8df0639c9/.idea/sonarlint/issuestore/3/9/39f75cef49943e1bc8c7916eaa81c80652536dd7 -------------------------------------------------------------------------------- /.idea/sonarlint/issuestore/7/4/746c35fcc923e7bbe07a6e1591eb777c6c0d28b0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achhibi/java21-new-features/064c440f4ec5c78b500f1f2152862de8df0639c9/.idea/sonarlint/issuestore/7/4/746c35fcc923e7bbe07a6e1591eb777c6c0d28b0 -------------------------------------------------------------------------------- /.idea/sonarlint/issuestore/8/8/88263ce9c5d2a4540209b8e0b0d6cef230bb0f48: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achhibi/java21-new-features/064c440f4ec5c78b500f1f2152862de8df0639c9/.idea/sonarlint/issuestore/8/8/88263ce9c5d2a4540209b8e0b0d6cef230bb0f48 -------------------------------------------------------------------------------- /.idea/sonarlint/issuestore/8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achhibi/java21-new-features/064c440f4ec5c78b500f1f2152862de8df0639c9/.idea/sonarlint/issuestore/8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d -------------------------------------------------------------------------------- /.idea/sonarlint/issuestore/e/2/e23996953c6018604d314386faac3307ab1deff3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achhibi/java21-new-features/064c440f4ec5c78b500f1f2152862de8df0639c9/.idea/sonarlint/issuestore/e/2/e23996953c6018604d314386faac3307ab1deff3 -------------------------------------------------------------------------------- /.idea/sonarlint/issuestore/f/5/f54cb9ff57f15fcb82cf19733a6dfc11dd81f491: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achhibi/java21-new-features/064c440f4ec5c78b500f1f2152862de8df0639c9/.idea/sonarlint/issuestore/f/5/f54cb9ff57f15fcb82cf19733a6dfc11dd81f491 -------------------------------------------------------------------------------- /.idea/sonarlint/securityhotspotstore/1/e/1e5acdc91df03a2e9f85c23862cfae48d609b93a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achhibi/java21-new-features/064c440f4ec5c78b500f1f2152862de8df0639c9/.idea/sonarlint/securityhotspotstore/1/e/1e5acdc91df03a2e9f85c23862cfae48d609b93a -------------------------------------------------------------------------------- /.idea/sonarlint/securityhotspotstore/3/9/39f75cef49943e1bc8c7916eaa81c80652536dd7: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achhibi/java21-new-features/064c440f4ec5c78b500f1f2152862de8df0639c9/.idea/sonarlint/securityhotspotstore/3/9/39f75cef49943e1bc8c7916eaa81c80652536dd7 -------------------------------------------------------------------------------- /.idea/sonarlint/securityhotspotstore/7/4/746c35fcc923e7bbe07a6e1591eb777c6c0d28b0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achhibi/java21-new-features/064c440f4ec5c78b500f1f2152862de8df0639c9/.idea/sonarlint/securityhotspotstore/7/4/746c35fcc923e7bbe07a6e1591eb777c6c0d28b0 -------------------------------------------------------------------------------- /.idea/sonarlint/securityhotspotstore/8/8/88263ce9c5d2a4540209b8e0b0d6cef230bb0f48: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achhibi/java21-new-features/064c440f4ec5c78b500f1f2152862de8df0639c9/.idea/sonarlint/securityhotspotstore/8/8/88263ce9c5d2a4540209b8e0b0d6cef230bb0f48 -------------------------------------------------------------------------------- /.idea/sonarlint/securityhotspotstore/8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achhibi/java21-new-features/064c440f4ec5c78b500f1f2152862de8df0639c9/.idea/sonarlint/securityhotspotstore/8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d -------------------------------------------------------------------------------- /.idea/sonarlint/securityhotspotstore/e/2/e23996953c6018604d314386faac3307ab1deff3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achhibi/java21-new-features/064c440f4ec5c78b500f1f2152862de8df0639c9/.idea/sonarlint/securityhotspotstore/e/2/e23996953c6018604d314386faac3307ab1deff3 -------------------------------------------------------------------------------- /.idea/sonarlint/securityhotspotstore/f/5/f54cb9ff57f15fcb82cf19733a6dfc11dd81f491: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achhibi/java21-new-features/064c440f4ec5c78b500f1f2152862de8df0639c9/.idea/sonarlint/securityhotspotstore/f/5/f54cb9ff57f15fcb82cf19733a6dfc11dd81f491 -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | 24 | 29 | 30 | 31 | 33 | 34 | 36 | { 37 | "associatedIndex": 1 38 | } 39 | 40 | 41 | 44 | 63 | 64 | 65 | 77 | 78 | 90 | 91 | 104 | 105 | 116 | 117 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 1702323059151 158 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Testing Java 21 New Features 2 | 3 | This project contains examples of code to test the new features of Java 21 with sample Main class. 4 | 5 | ## Features tested 6 | 7 | * InstanceMainMethodLauncher 8 | * RecordPattern 9 | * SequencedCollection 10 | * StringTemplate 11 | * UnnamedClass 12 | * ScopedValueUsageTest 13 | 14 | ## Examples 15 | 16 | Each feature is represented by a java file containing one or more examples of code. 17 | 18 | ### UnnamedClass 19 | 20 | ``` 21 | 22 | /** 23 | ** java --enable-preview --source 21 UnnamedClass.java 24 | **/ 25 | static String staticField = "I'm static field"; 26 | String istanceField = "I'm instance field"; 27 | private String privateInstanceField = "I'm private instance field"; 28 | 29 | void main() { 30 | System.out.printf("%s%n", staticField); 31 | System.out.printf("%s%n", istanceField); 32 | System.out.printf("%s%n", privateInstanceField); 33 | } 34 | 35 | ``` 36 | 37 | ### StringTemplate 38 | 39 | ``` 40 | public class StringTemplateSample { 41 | public static void main(String[] args) { 42 | var productName = "IPhone 15"; 43 | var productPrice = 1129.99; 44 | var productAvailable = true; 45 | 46 | String productInfo = STR.""" 47 | Product: \{productName} Price: \{productPrice} Availability: \{productAvailable ? "In Stock" : "Out of Stock"} 48 | """; 49 | System.out.println(productInfo); 50 | 51 | } 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.example 8 | java21-new-features 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 21 13 | 21 14 | UTF-8 15 | 16 | 17 | 18 | org.projectlombok 19 | lombok 20 | 1.18.30 21 | 22 | 23 | 24 | 25 | 26 | org.apache.maven.plugins 27 | maven-compiler-plugin 28 | 29 | 21 30 | 21 31 | 32 | --enable-preview 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/org/amch/InstanceMainMethodLauncher.java: -------------------------------------------------------------------------------- 1 | package org.amch; 2 | 3 | class InstanceMainMethodLauncher { 4 | 5 | /** 6 | * To run: `java --enable-preview --source 21 org.amch.InstanceMainMethodLauncher.java` 7 | */ 8 | void main() { 9 | System.out.println("Hello world:> from instance main method JAVA21"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/amch/RecordPattern.java: -------------------------------------------------------------------------------- 1 | package org.amch; 2 | 3 | 4 | import java.util.List; 5 | 6 | public class RecordPattern { 7 | public static void main(String[] args) { 8 | testInstanceof(); 9 | testSwitch(); 10 | genericInferenceTest(); 11 | } 12 | 13 | public static void testInstanceof() { 14 | System.out.println("=== instanceof example ==="); 15 | var point = new Point(10, 10); 16 | var coloredPoint = new ColoredPoint(point, "blue"); 17 | Object obj = coloredPoint; 18 | 19 | // java 16 20 | if (obj instanceof ColoredPoint cp) { 21 | System.out.println("obj is a ColoredPoint: " + cp); 22 | } 23 | 24 | if (obj instanceof Point p) { 25 | System.out.println("obj is a point: " + p); 26 | } else { 27 | System.out.println("obj is not a point"); 28 | } 29 | 30 | // java 20 31 | if ( obj instanceof ColoredPoint(Point(int x, var y), String color) ) { 32 | System.out.printf("Point [%d,%d] has color %s%n", x, y, color); 33 | } 34 | } 35 | 36 | public static void testSwitch() { 37 | System.out.println("=== switch example ==="); 38 | var list = List.of( 39 | new Decorator(new Point(21, 21)), 40 | new Decorator(new ColoredPoint(new Point(42, 42), "red")), 41 | new Decorator("test") 42 | ); 43 | 44 | for (Decorator d : list) { 45 | switch (d) { 46 | case Decorator(Point(var x, var y)) -> { 47 | System.out.printf("Point [%d,%d]%n", x, y); 48 | } 49 | case Decorator(ColoredPoint(Point(var x, var y), String color)) -> { 50 | System.out.printf("ColoredPoint [%d,%d] with color %s%n", x, y, color); 51 | } 52 | case Decorator(String s) -> { 53 | System.out.println("Decorated string: " + s); 54 | } 55 | // required to be exhaustive 56 | default -> System.out.println("None matched"); 57 | } 58 | } 59 | } 60 | 61 | public static void genericInferenceTest() { 62 | System.out.println("=== generic type inference example ==="); 63 | var point = new Point(42, 42); 64 | var decoratedPoint = new Decorator(new ColoredPoint(point, "RED")); 65 | var anotherDecorated = new Decorator(decoratedPoint); 66 | 67 | // JDK 20: type inference in Decorator(Decorator(T)) 68 | if (anotherDecorated instanceof Decorator(Decorator(ColoredPoint(Point(int x, int y), String color)))) { 69 | System.out.printf("x=%d, y=%d; color=%s%n%n", x, y, color); 70 | } 71 | } 72 | } 73 | 74 | record Point(int x, int y) {} 75 | 76 | record ColoredPoint(Point p, String color) {} 77 | 78 | record Decorator(T t) {} 79 | -------------------------------------------------------------------------------- /src/main/java/org/amch/ScopedValueUsageTest.java: -------------------------------------------------------------------------------- 1 | package org.amch; 2 | 3 | public class ScopedValueUsageTest { 4 | final static ScopedValue SCOPE = ScopedValue.newInstance(); 5 | 6 | public static void main(String[] args) { 7 | System.out.println("main start"); 8 | 9 | ScopedValue.where(SCOPE, "message from main") 10 | .run(() -> { 11 | var worker = new Worker(); 12 | worker.execute(); 13 | }); 14 | System.out.println("main ending"); 15 | } 16 | } 17 | 18 | class Worker { 19 | final static ScopedValue WORKER_SCOPE = ScopedValue.newInstance(); 20 | 21 | public void execute() { 22 | System.out.println(STR."shared value from main: \{ScopedValueUsageTest.SCOPE.get()}"); 23 | 24 | // === Nested Scope === 25 | ScopedValue.where(WORKER_SCOPE, "message from worker") 26 | .run(() -> { 27 | var messageFromMain = ScopedValueUsageTest.SCOPE.get(); 28 | var messageFromWorker = WORKER_SCOPE.get(); 29 | System.out.println(STR."shared value to inner scope from main: \{messageFromMain}"); 30 | System.out.println(STR."shared value to inner scope from worker: \{messageFromWorker}"); 31 | }); 32 | 33 | 34 | ScopedValue.where(ScopedValueUsageTest.SCOPE, "message from worker over main") 35 | .run(() -> { 36 | var remindedMessage = ScopedValueUsageTest.SCOPE.get(); 37 | System.out.println(STR."shared value from shadowed scope: \{remindedMessage}"); 38 | }); 39 | 40 | System.out.println(STR."shared value from main after all scopes: \{ScopedValueUsageTest.SCOPE.get()}"); 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/org/amch/SequencedCollectionTest.java: -------------------------------------------------------------------------------- 1 | package org.amch; 2 | 3 | import java.util.*; 4 | 5 | public class SequencedCollectionTest { 6 | public static void main(String[] args) { 7 | testCollections(); 8 | testSets(); 9 | testMaps(); 10 | } 11 | 12 | public static void testCollections() { 13 | System.out.println("* List"); 14 | 15 | List list = new ArrayList<>(); 16 | SequencedCollection sequenced = new ArrayList<>(); 17 | 18 | list.add("1"); 19 | sequenced.add("1"); 20 | System.out.println("=============== INIT ============="); 21 | print(list, sequenced); 22 | 23 | 24 | list.set(0, "First"); 25 | sequenced.addFirst("First"); 26 | 27 | System.out.println("=============== FIRST ============="); 28 | print(list, sequenced); 29 | 30 | // add last (tail) 31 | list.add("last"); 32 | sequenced.addLast("last"); 33 | 34 | System.out.println("=============== LAST ============="); 35 | print(list, sequenced); 36 | 37 | // get first 38 | list.get(0); 39 | sequenced.getFirst(); 40 | 41 | // get last 42 | list.get(list.size() - 1); 43 | sequenced.getLast(); 44 | 45 | // remove first 46 | list.remove(0); 47 | sequenced.removeFirst(); 48 | System.out.println("=============== REMOVE FIRST ============="); 49 | print(list, sequenced); 50 | 51 | // remove last 52 | list.remove(list.size() - 1); 53 | sequenced.removeLast(); 54 | System.out.println("=============== REMOVE LAST ============="); 55 | print(list, sequenced); 56 | 57 | // descending iterator 58 | ListIterator reversed = list.listIterator(list.size()); 59 | while (reversed.hasPrevious()) { 60 | reversed.previous(); 61 | } 62 | Iterator reversedSequence = sequenced.reversed().iterator(); 63 | } 64 | 65 | public static void testSets() { 66 | System.out.println("* Set"); 67 | 68 | Set set = new LinkedHashSet<>(); 69 | SequencedSet sequenced = new LinkedHashSet<>(); 70 | 71 | set.add("1"); 72 | sequenced.add("1"); 73 | System.out.println("=============== INIT ============="); 74 | print(set, sequenced); 75 | 76 | 77 | set.iterator().next(); 78 | sequenced.getFirst(); 79 | 80 | // get last 81 | Iterator iterator = set.iterator(); 82 | String last; 83 | while (iterator.hasNext()) 84 | last = iterator.next(); 85 | last = sequenced.getLast(); 86 | 87 | // descending iterator 88 | Iterator descendingIterator = new TreeSet<>(set).descendingSet().iterator(); 89 | descendingIterator = sequenced.reversed().iterator(); 90 | } 91 | 92 | public static void testMaps() { 93 | System.out.println("* Map"); 94 | Map map = new LinkedHashMap<>(); 95 | SequencedMap sequenced = new LinkedHashMap<>(); 96 | 97 | map.put("1", "v1"); 98 | sequenced.put("1", "v1"); 99 | System.out.println("============= INIT ============="); 100 | print(map, sequenced); 101 | 102 | // put first 103 | map.put("first", "v2"); 104 | sequenced.putFirst("first", "v2"); 105 | System.out.println("============= FIRST ============="); 106 | print(map, sequenced); 107 | 108 | // get first 109 | var entry = map.entrySet().iterator().next(); 110 | entry = sequenced.firstEntry(); 111 | 112 | // put last 113 | map.put("last", "v2"); 114 | sequenced.putLast("last", "v2"); 115 | System.out.println("============= LAST ============="); 116 | print(map, sequenced); 117 | 118 | // get last 119 | var iterator = map.entrySet().iterator(); 120 | while (iterator.hasNext()) 121 | entry = iterator.next(); 122 | entry = sequenced.lastEntry(); 123 | 124 | // reverse 125 | var reversedIterator = sequenced.reversed().entrySet().iterator(); 126 | } 127 | 128 | public static void print(Collection collection, SequencedCollection newCollection) { 129 | System.out.printf("Collection: %s%n", collection); 130 | System.out.printf("Sequenced: %s%n", newCollection); 131 | } 132 | 133 | public static void print(Map collection, SequencedMap newCollection) { 134 | System.out.printf("Map: %s%n", collection); 135 | System.out.printf("SequencedMap: %s%n", newCollection); 136 | } 137 | } -------------------------------------------------------------------------------- /src/main/java/org/amch/StringTemplateSample.java: -------------------------------------------------------------------------------- 1 | package org.amch; 2 | 3 | public class StringTemplateSample { 4 | public static void main(String[] args) { 5 | var productName = "IPhone 15"; 6 | var productPrice = 1129.99; 7 | var productAvailable = true; 8 | 9 | String productInfo = STR.""" 10 | Product: \{productName} Price: \{productPrice} Availability: \{productAvailable ? "In Stock" : "Out of Stock"} 11 | """; 12 | 13 | System.out.println(productInfo); 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/amch/StringTemplateTest.java: -------------------------------------------------------------------------------- 1 | package org.amch; 2 | import java.time.*; 3 | import java.time.format.DateTimeFormatter; 4 | 5 | public class StringTemplateTest { 6 | static FamilyRelation type = FamilyRelation.FATHER; 7 | static String firstName = "Amor"; 8 | static String lastName = "CHHIBI"; 9 | static String childName = "Anass"; 10 | 11 | public static void main(String[] args) { 12 | rawTemplateProcessor(); 13 | simpleTemplate(); 14 | allowedExpressionsInsideEmbeddedTemplate(); 15 | } 16 | 17 | static void rawTemplateProcessor() { 18 | StringTemplate st = StringTemplate.RAW."String template built from RAW template processor: \{firstName}"; 19 | String message = java.lang.StringTemplate.STR.process(st); 20 | // same as 21 | message = STR."String template built from RAW template processor: \{firstName}"; 22 | System.out.println(message); 23 | } 24 | 25 | static void simpleTemplate() { 26 | // STR template processor returns a string 27 | String str = STR."Simple string template without embedded expression"; 28 | 29 | // we can use template embedded with string literal 30 | System.out.println(STR."Wake up \{childName}..."); 31 | 32 | // we can also use template expression with template string 33 | System.out.println(STR.""" 34 | Mr. \{lastName}! Welcome back, we missed you! 35 | """); 36 | 37 | // we can multiline the embedded expression 38 | System.out.println(STR."The time is \{ 39 | DateTimeFormatter 40 | .ofPattern("HH:mm:ss") 41 | .format(LocalTime.now()) 42 | } right now"); 43 | 44 | // we don't need to escape " 45 | System.out.println(STR."Follow the white \{"rabbit"}..."); 46 | } 47 | 48 | // we can use any Java expression 49 | static void allowedExpressionsInsideEmbeddedTemplate() { 50 | boolean isCaptured = true; 51 | 52 | // arithmetic expression 53 | var counter = 0; 54 | System.out.println(STR."Counting... \{++counter}... \{++counter}... \{++counter}..."); 55 | System.out.println(STR."How long has he been arrested? \{4 + 2} hours"); 56 | System.out.println(STR."How long is his name? \{firstName.length() + lastName.length()}"); 57 | 58 | // call method 59 | System.out.println(STR."In what language his first program.\n? \{greetings()}"); 60 | 61 | // ternary expression 62 | System.out.println(STR."As you can see Mr. \{ 63 | isCaptured ? lastName : childName 64 | }, we've been tracking you..."); 65 | 66 | // switch expression 67 | System.out.println(STR."What is he? \{ 68 | switch (type) { 69 | case FATHER -> "Papa"; 70 | case CHILD -> "Fiston"; 71 | } 72 | }"); 73 | } 74 | 75 | static String greetings() { 76 | return "- java -"; 77 | } 78 | } 79 | 80 | enum FamilyRelation { 81 | FATHER, 82 | CHILD 83 | } -------------------------------------------------------------------------------- /src/main/java/org/amch/UnnamedClass.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * java --enable-preview --source 21 UnnamedClass.java 3 | */ 4 | static String staticField = "I'm a static field"; 5 | String istanceField = "I'm an instance field"; 6 | private String privateInstanceField = "I'm a private instance field"; 7 | 8 | void main() { 9 | System.out.printf("%s%n", staticField); 10 | System.out.printf("%s%n", istanceField); 11 | System.out.printf("%s%n", privateInstanceField); 12 | } 13 | static void instanceMethod() { 14 | System.out.println("can have any instance method"); 15 | } 16 | static void staticMethod() { 17 | System.out.println("can have static method"); 18 | } --------------------------------------------------------------------------------