The dev.java website is a huge resource for all Java developers. Here are 11 tricks collected from the site.
Download a PDF of this article
Trick #1: Compact record constructors
You know how to use records to model data carriers and how to verify incoming data during construction, but do you know that you don’t have to list the parameters of all the record constructors?
A record’s canonical constructor has one argument per component but in its compact form, you don’t have to list all the arguments. You can’t assign fields—that happens in compiler-generated code after yours—but you can reassign the parameters, which leads to the same result.
public record Range(int start, int end) {
public Range {
if (end <= start) {
throw new IllegalArgumentException();
}
}
}
Trick #2: Serializing records
You know that every object can be serialized using black magic, but do you know that no such deviance is needed for records? The guaranteed presence of constructor parameters and accessors makes serialization work with the object model—and makes it easy for you to create reliable serializable records.
Trick #3: jpackage versus modules
You know jpackage, but wait: Do you really know jpackage?
jpackage is a command-line tool that takes an entire Java app as input and produces a fully self-contained application image, meaning it includes your code, dependencies, and a Java runtime. jpackage creates the runtime for your app with jlink, which you can fully configure through jpackage, or you can pass it the path to a runtime image that you already created.
Other configuration options for jpackage include the ability to specify application metadata such as icons and licenses, installation options, and launchers as well as JVM and program options.
jpackage produces output in platform-specific formats such as deb and rpm for Linux or exe and msi for Windows.
Now that you know jpackage, do you know that it can do all of that for modular as well as nonmodular applications?
# generate an application image for a modular application:
jpackage --type app-image -n name -p modulePath -m moduleName/className
# for a nonmodular application:
jpackage --type app-image -i inputDir -n name --main-class className --main-jar myJar.jar
Trick #4: Cross-OS runtime images
Speaking of jlink, do you know that you can use it to create runtime images across operating systems?
Say your build server runs Linux and you need a Windows runtime image. You simply need to download and unpack a Windows JDK of the same version as the Linux one that runs jlink, and then add the Windows jmods folder to the Linux jlink executable’s module path.
# download JDK for Windows and unpack into jdk-win
# create the image with the jlink binary from the system's JDK
# (in this example, Linux)
$ jlink
--module-path jdk-win/jmods:mods
--add-modules com.example.main
--output app-image
Trick #5: Labeled breaks and continues
You know how to use the break statement to get out of an inner loop, but do you know that you can give the break a label to break out of an appropriately labeled outer loop as well? You can do likewise with continue, which skips the rest of the current iteration of the innermost loop, because if you pass it a label, it will skip the iteration of the labeled loop instead.
However, just because you can, doesn’t mean you should. Use this trick with care.
class ContinueWithLabelDemo {
public static void main(String[] args) {
String searchMe = "Look for a substring in me";
String substring = "sub";
boolean foundIt = false;
int max = searchMe.length() -
substring.length();
test:
for (int i = 0; i <= max; i++) {
int n = substring.length();
int j = i;
int k = 0;
while (n-- != 0) {
if (searchMe.charAt(j++) != substring.charAt(k++)) {
continue test;
}
}
foundIt = true;
break test;
}
System.out.println(foundIt ? "Found it" : "Didn't find it");
}
}
Trick #6: Boolean expressions in pattern matching
You know pattern matching, but do you know that you can use the variable that pattern matching introduces in the same boolean expression?
For example, if you check whether the instance object is of type String with object instanceof String s, you can start using s straight away, such as to check whether s is nonempty with && !s.isEmpty(). This works in if statements in Java 16 and in switch as a preview in Java 17.
Object object = // ...
if (object instanceof String s && !s.isEmpty())
System.out.println("Non-empty string");
else
System.out.println("No string or empty.");
Trick #7: Generic wildcards and subtyping
You know generics and that a List<Integer> does not extend a List<Number>, as shown in Figure 1.
0 comments:
Post a Comment