Image source from: The arrival of Java 19
“ Module bundle together one or more packages, and offer stronger encapsulation than jars. ”
public
is no longer public to others.For more, here is my tutorial @IBM Developer:
Java 9+ modularity: The theory and motivations behind modularity.
For more, here is my two tutorials @IBM Developer:
Java 9+ modularity: Module basics and rules.
Java 9+ modularity: How to design packages and create modules, Part 1, and 2.
java --list-modules
jdeps -jdkinternals app.jar
jdeprscan app.jar
For more, here is my tutorial @IBM Developer:
Java 9+ modularity: The difficulties and pitfalls of migrating from Java 8 to Java 9+.
Each 2 years we will have an LTS Release.
jlink
tool is here, to generate our custom JRE.jlink
?Linker
jlink
can be used to link a set of modules, along with their transitive dependences,
to create a custom modular run-time image.
jshell
- Java 9For more, here is my two tutorials @IBM Developer:
Java theory and practice: Interactive Java programming (REPL) with JShell 12, Part 1, and 2.
.java
old days.java
with Java
- Java 11For more, here is my tutorial @IBM Developer:
Java theory and practice: Run single-file source code programs without compilation.
var
type - Java 10For more, here is my tutorial @InfoQ:
Explore the New Java 10 βvarβ Type: An Introduction and Hands-on Tutorial.
var
) Syntax for Lambda Parameters - Java 11(String a, String b) -> a.concat(b)
( a, b) -> a.concat(b)
(var a, var b) -> a.concat(b)
(@Nullable var a, @Nonnull var b) -> a.concat(b)
Save this code in a file named dirlist
without any extension and then mark it as executable:
mohamed_taman:code$ chmod +x dirlist
HttpClient
and WebSocket
APIHttpClient
and WebSocket
APIs originally shipped with JDK 9 under the Java Enhancement Proposal JEP 110 as part of an incubator module named jdk.incubator.httpclient
.java.net.http
and brought into the mainstream in JDK 11 under JEP 321.HttpClient
, HttpRequest
, HttpResponse
, and WebSocket
.
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(create("https://postman-echo.com/get/"))
.build();
client.sendAsync(request, ofString())
.thenApply(HttpResponse::body)
.thenAccept(out::println)
.join();
For more, here is my tutorial @IBM Developer:
Java theory and practice: Explore the new Java SE 11 HTTP Client and WebSocket APIs.
First implement the WebSocket.Listener
interface:
public final class EchoListener implements WebSocket.Listener {
@Override
public void onOpen(WebSocket webSocket) {
logger.info("CONNECTED");
....
}
....
}
use an HttpClient
to create a WebSocket
WebSocket webSocket = httpClient.newWebSocketBuilder()
.buildAsync(URI.create("ws://demos.kaazing.com/echo"),
new EchoListener(executor)).join();
webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok").thenRun(() -> logger.info("Sent close")).join();
jshell> String getRomanNumber(int value){
String romanValue = "";
switch(value){
case 0: romanValue = "nulla";
break;
case 1: romanValue = "I";
break;
case 2: romanValue = "II";
break;
case 3: romanValue = "III";
break;
case 4: romanValue = "IV";
break;
case 5: romanValue = "V";
break;
case 6: romanValue = "VI";
break;
case 7: romanValue = "VII";
break;
case 8: romanValue = "VIII";
break;
case 9: romanValue = "IX";
break;
case 10: romanValue = "X";
break;
default: System.out.printf("Out of range value: %d %n", value);
romanValue = "N/A";
break;
}
return romanValue;
}
mohamed_taman:~$ jshell --enable-preview
String getRomanNumber(int value){
String romanValue = "";
switch(value){
case 0 -> romanValue = "nulla";
case 1 -> romanValue = "I";
case 2 -> romanValue = "II";
case 3 -> romanValue = "III";
case 4 -> romanValue = "IV";
case 5 -> romanValue = "V";
case 6 -> romanValue = "VI";
case 7 -> romanValue = "VII";
case 8 -> romanValue = "VIII";
case 9 -> romanValue = "IX";
case 10 -> romanValue = "X";
default -> {
System.out.printf("Out of range value: %d %n", value);
romanValue = "N/A";
}
}
return romanValue;
}
String getRomanNumber(int value){
return switch(value){
case 0 -> "nulla";
case 1 -> "I";
case 2 -> "II";
case 3 -> "III";
case 4 -> "IV";
case 5 -> "V";
case 6 -> "VI";
case 7 -> "VII";
case 8 -> "VIII";
case 9 -> "IX";
case 10 -> "X";
default -> throw new IllegalStateException("Out of range value: " + value);
};
}
jshell> String getOddOrEvenNumber(int value){
String kind = "N/A";
switch(value){
case 0: kind = "Zero"; break;
case 1:
case 3:
case 5:
case 7:
case 9: kind = "Odd"; break;
case 2:
case 4:
case 6:
case 8:
case 10: kind = "Even"; break;
default: System.out.printf("Out of range: %d %n", value);
}
return kind;
}
jshell> var kind = switch(value){
...> case 0 -> "Zero";
...> case 1, 3, 5, 7, 9 -> "Odd";
...> case 2, 4, 6, 8, 10 -> "Even";
...> default -> throw new IllegalStateException("Out of range: " + value);
...> };
For more, here is my tutorial @IBM Developer:
Effective use of the new switch statement and expression in Java SE 12.
jshell>var value = 3
value ==> 3
jshell> String kind = switch(value){
...> case 0: break "Zero";
...> case 1, 3, 5, 7, 9: break "Odd";
...> case 2, 4, 6, 8, 10: break "Even";
...> default: throw new Exception("Out of range: " + value);};
kind ==> "Odd"
Dropping break & introducing yield
jshell> value = 10
value ==> 10
jshell> String kind = switch(value){
...> case 0: yield "Zero";
...> case 1, 3, 5, 7, 9: yield "Odd";
...> case 2, 4, 6, 8, 10: yield "Even";
...> default: throw new Exception("Out of range: " + value);};
kind ==> "Even"
This is why community feedback is important, & the preview feature is great for such changes. - In Java 14 switch expressions is standardized.
Text Blocks
(Preview) - Java 13var html = "\n" +
"<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";
var html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
//Old Days
if (obj instanceof String) {
// Need to declare & cast again the object
String str = (String) obj;
.. str.contains(..) ..
}else{
.. str = ....
}
//Java 14 Onwards
if (obj instanceof String str) {
// No need to declare str object again with casting
.. str.contains(..) ..
} else {
.. str....
}
//More complex examples
if (obj instanceof String str && str.length() > 5) { .. str.contains(..) .. }
The use of pattern matching in instanceof should dramatically reduce the overall number of explicit casts in Java programs.
constructors
, accessors
, equals()
, hashCode()
, toString()
, etc. To avoid this repetitive code, Java introduced records. In the Second preview it works well with Sealed Classes, and could be declared locally.final class Point {
public final int x;
public final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
// state-based implementations of equals, hashCode, toString
// nothing else
record Point(int x, int y) { }
a.i = 99;
Exception in thread "main" java.lang.NullPointerException
at Prog.main(Prog.java:5)
a.b.c.i = 99;
Exception in thread "main" java.lang.NullPointerException:
Cannot read field 'c' because 'a.b' is null.
at Prog.main(Prog.java:5)
package com.example.geometry;
public sealed class Shape
permits Circle, Rectangle, Square {...}
public final class Circle extends Shape {...}
public sealed class Rectangle extends Shape
permits TransparentRectangle, FilledRectangle {...}
public final class TransparentRectangle extends Rectangle {...}
public final class FilledRectangle extends Rectangle {...}
public non-sealed class Square extends Shape {...}
sealed interface Car permits BMW, Audi { ... }
record BMW(int price) implements Car { ... }
record Audi(int price, String model) implements Car { ... }
List<Merchant> findTopMerchants(List<Merchant> merchants, int month) {
// Local record
record MerchantSales(Merchant merchant, double sales) {}
return merchants.stream()
.map(merchant -> new MerchantSales(merchant, computeSales(merchant, month)))
.sorted((m1, m2) -> Double.compare(m2.sales(), m1.sales()))
.map(MerchantSales::merchant)
.toList();
}
π
String
class new enhancementsString repeat(int)
- Java 11
jshell> "no ".repeat(14).trim().concat(", Batman!")
$1 ==> "no no no no no no no no no no no no no no, Batman!
boolean isBlank()
- Java 11
jshell>var blankText = " "
blankText ==> " "
jshell>blankText.trim().length() == 0
$2 ==> true
jshell>blankText.isBlank()
$3 ==> true
String stripLeading()
- Java 11String stripTrailing()
- Java 11String strip()
- Java 11
jshell>var textWithSpaces = "\n \t Text \u2005"
textWithSpaces ==> "\n \t Text "
jshell>textWithSpaces.trim()
$4 ==> "Text "
jshell>textWithSpaces.strip()
$5 ==> "Text"
Stream lines()
- Java 11
jshell> "\nOne\nTwo\nThree\nFour".lines().forEach(System.out::println)
One
Two
Three
Four
String indent(int)
- Java 12
jshell> "\nOne\nTwo\nThree\nFour".indent(5).indent(-2).lines().forEach(System.out::println)
... One
... Two
... Three
... Four
String transform(Function)
- Java 12
jshell> var text = "Text with*out *some* *asterisks"
text ==> "Text wi*th *some* * asterisks"
jshell> text.transform(String::toUpperCase)
...> .transform(s -> s.replaceAll("\\*", ""))
...> .transform(s -> s.split(" "))
$1 ==> String[4] { "TEXT", "WITHOUT", "SOME", "ASTERISKS" }
For more, here is my tutorial @IBM Developer:
Java theory and practice: Explore new Java SE 11 and 12 APIs and language features.
String formatted(Object[])
jshell> "Hello %s!".formatted("World")
| Warning:
| formatted(java.lang.Object...) in java.lang.String has been deprecated and marked for removal
| "Hello %s!".formatted("World")
| ^-------------------^
$11 ==> "Hello World!"
String stripIndent()
jshell> var s1 = " foo\n bar"
s1 ==> " foo\n bar"
jshell> System.out.println(s1); System.out.println(s1.stripIndent())
foo
bar
foo
bar
| Warning:
| stripIndent() in java.lang.String has been deprecated and marked for removal
| System.out.println(s1.stripIndent())
| ^------------^
String translateEscapes()
jshell> System.out.println("\n".equals("\\n".translateEscapes()))
true
| Warning:
| translateEscapes() in java.lang.String has been deprecated and marked for removal
| System.out.println("\n".equals("\\n".translateEscapes())); // true
| ^--------------------^
The curious ones out there will quickly spot that all the new methods are deprecated for removal
@Deprecated(forRemoval=true, since="13")
CompactNumberFormat
- Java 12Refers to the representation of a number in a short or human-readable form. For example, in the en_US locale, 1000 can be formatted as β1Kβ and 1000000 as β1Mβ.
For more, here is my tutorial @IBM Developer:
Java theory and practice: Explore new Java SE 11 and 12 APIs and language features.
java.time
- Java 16
Developers might want to express periods in a day, such as βin the morning," "in the afternoon," or βat night,β
not just a.m. or p.m.
For more, here is my article @Java Magazine:
Hidden gems in Java 16 and Java 17, from Stream.mapMulti to HexFormat.
Teeing
Collectors method - Java 12what could we do with case such as this:
is π 1 == π 2 ??
It will compare all bytes and return -1 if match, otherwise will return the location of the first mismatching byte.
java.net.Socket
and java.net.ServerSocket
API implementations date back to JDK 1.0.NioSocketImpl
, which no longer requires native code, thus simplifying the act of porting to multiple platforms.java.util.concurrent
locks rather than synchronized methods.Write this on macOS or Linux
Read it on Windows OS
you will get this:
For more, here is my article @Java Magazine:
The not-so-hidden gems in Java 18: The JDK Enhancement Proposals.
To control the JVM:
-XX:ActiveProcessorCount=<n>
,
-XX:InitialRAMPercentage
-XX:MinRAMPercentage
,
-XX:MaxRAMPercentage
Since Java 9 Garbage First Garbage Collector (G1GC) was made the default GC.
-XX:+UnlockExperimentalVMOptions
-XX:+UseEpsilonGC
-XX:+UnlockExperimentalVMOptions
-XX:+UseZGC
New things come ... and sometimes old things have to go π
java.se.ee
- related modulesThe affected modules are:
corba
transaction
activation
xml.bind
xml.ws
xml.ws.annotation
org.openjfx
javafx-controls
12.0.1
org.openjfx
javafx-maven-plugin
0.0.2
HelloFX
Micro-benchmarking is a performance-oriented practice that can steer implementation choices in code.
JMH allows you to write a simple Java class containing several methods that can be turned into a micro-benchmark using annotations. Many configuration options for the benchmark can also be configured through annotations.
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.runner.*;
import org.openjdk.jmh.runner.options.*;
public class MyBenchmark {
@Benchmark
public void testMethod() {
int a = 1;
int b = 2;
int sum = a + b;
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(MyBenchmark.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}}
For more visit official OpenJDK website:
OpenJDK JMH tool, and this is a good tutorial
JMH - Java Microbenchmark Harness
VisualVM is a visual tool integrating command line JDK tools and lightweight profiling capabilities. Designed for both development and production time use.
For more visit VisualVM official website:
https://visualvm.github.io/index.html
Flight Recorder is a low-overhead, data-collection framework for the JVM.
jwebserver
command. By default, this command listens to localhost on port 8000. The server also provides a file browser to the current directory.[mtaman]:~ jwebserver
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving /Users/mohamed_taman/Hidden Gems in Java 18/code and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/
For more visit official my latest articles about JDK 18:
The not-so-hidden gems in Java 18: The JDK Enhancement Proposals,
and
The hidden gems in Java 18: The subtle changes