├── .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 |
11 |
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 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | {
37 | "associatedIndex": 1
38 | }
39 |
40 |
41 |
42 |
43 |
44 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | 1702323059151
158 |
159 |
160 | 1702323059151
161 |
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 | }
--------------------------------------------------------------------------------