avatarBen Weidig

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

3386

Abstract

js-keyword">new</span> <span class="hljs-type">Files</span>.<span class="hljs-keyword">new</span><span class="hljs-type">BufferedWriter</span>(...) ) { ... } <span class="hljs-comment">// After this block first 'writer', then 'reader' will be closed.</span></pre></div><p id="71aa">The <i>try-with-resources</i> statement is also a normal <code>try</code>-block, so feel free to add <code>catch</code> or <code>finally</code> blocks, they are run <i>after</i> the resources are closed.</p><p id="f5a5">Only caveat is exception handling… of course the closing of resources can throw exceptions. But what happens if our code in the <code>try</code> block throws an exception <i>AND</i> the closing of the resource throws another one? In this case Java surpresses the closing exceptions, but they are reachable via <code>#getSurpressed()</code> of the exception, curtosy of <code>java.lang.Throwable</code>.</p><h1 id="7d7f">switch with String literals</h1><p id="f19b">Starting with Java 8 the <code>switch</code> statement is capable of handling String literals for its <code>case</code> blocks:</p><div id="1ead"><pre><span class="hljs-type">String</span> mode = ... <span class="hljs-keyword">switch</span> (mode) { <span class="hljs-keyword">case</span> <span class="hljs-string">"DEV"</span>: ... <span class="hljs-keyword">break</span>;</pre></div><div id="27b7"><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"PROD"</span>: ... <span class="hljs-keyword">break</span>;</pre></div><div id="e98a"><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"QA"</span>: ... <span class="hljs-keyword">break</span>;</pre></div><div id="73a5"><pre> <span class="hljs-keyword">default</span>: ... <span class="hljs-keyword">break</span>; }</pre></div><p id="22a5">The comparison is case-sensitive because <code>String#equals</code> is used. <code>switch</code> statements generate more efficient bytecode compared to lots of chained <code>if-then-else</code>.</p><h1 id="f926">Binary literal</h1><p id="9859">I don’t work much with binary in my code, but it’s still a nice addition: integral types (<code>byte</code>, <code>short</code>, <code>int</code>, <code>long</code>) are now as easily declarable as hex-number:</p><div id="8c5d"><pre><span class="hljs-comment">// Hex</span> <span class="hljs-built_in">int</span> asHex = <span class="hljs-number">0x25</span> <span class="hljs-comment">// = 35</span></pre></div><div id="9b56"><pre>// NEW: Binary int asBinary = <span class="hljs-number">0b100011</span> // = <span class="hljs-number">35</span></pre></div><p id="8fca">We can either use <code>0b</code> or <code>0B</code> as prefix, and might left-pad the value with as many zeros as needed.</p><p id="c919">The advantage here is that you can better visualize and compare binary variables that might have a direct relationship to another, which wouldn’t be visible in another form of representation.</p><h1 id="7786">Improved numeric literals</h1><p id="d208">Numeric literals (including the new binary literal) can now be written in a more comprehensible way, with underscores as separators:</p><div id="555d"><pre>// OLD long oldCc = 4111111111111111l; long oldHex = <span class="hljs-number">0xAAFF23C522</span>; long oldBinary = <span class="hljs-number">0b1

Options

11000010111</span>;</pre></div><div id="1e0b"><pre>// NEW long cc <span class="hljs-operator">=</span> <span class="hljs-number">4111</span>_1111_1111_1111l<span class="hljs-comment">;</span> long hex <span class="hljs-operator">=</span> <span class="hljs-number">0</span>xAA_FF_23_C5_22<span class="hljs-comment">;</span> long binary <span class="hljs-operator">=</span> <span class="hljs-number">0</span>b1110_0001_0111<span class="hljs-comment">;</span></pre></div><p id="c8b7">Some restrictions occur on the placement of the underscore though:</p><ul><li>not at the beginning or end of a number</li><li>not adjacent to the decimal point</li><li>not adjacent to prefixes/suffixes (e.g. 0x, f)</li></ul><h1 id="75b2">Multiple Exceptions</h1><p id="f02c">Instead of multiple <code>catch</code> blocks we can now catch multiple exception types in a single block. It’s nice to have as many different <code>catch</code> blocks as we might need, but if handling them doesn’t differ we combine them with the pipe symbol <code>|</code>:</p><div id="55fe"><pre>// OLD <span class="hljs-built_in">try</span> { ... } <span class="hljs-built_in">catch</span> (NullPointerException ex) { ... } <span class="hljs-built_in">catch</span> (IllegalArgumentException ex) { ... }</pre></div><div id="a2e7"><pre><span class="hljs-string">//</span> NEW <span class="hljs-keyword">try</span> { <span class="hljs-string">...</span> } catch <span class="hljs-params">(NullPointerException | IllegalArgumentException ex)</span> { <span class="hljs-string">...</span> }</pre></div><p id="61f6">The generated bytecode won’t duplicate any code and will be smaller and more efficient compared to multiple identical <code>catch</code> blocks.</p><h1 id="8870">Improved generic type inference for creation</h1><p id="a0f4">Generics are great except typing so many types:</p><div id="f01c"><pre><span class="hljs-comment">// OLD</span> <span class="hljs-built_in">Map</span><Long, <span class="hljs-built_in">List</span><<span class="hljs-built_in">String</span>>> <span class="hljs-built_in">map</span> = <span class="hljs-literal">new</span> HashMap<<span class="hljs-built_in">String</span>, <span class="hljs-built_in">List</span><<span class="hljs-built_in">String</span>>>();</pre></div><p id="6e9e">With Java 7 we don’t need to specify the types on the creation part thanks to the diamond operator: <code><></code>:</p><div id="6939"><pre><span class="hljs-comment">// NEW</span> <span class="hljs-built_in">Map</span><Long, <span class="hljs-built_in">List</span><<span class="hljs-built_in">String</span>>> <span class="hljs-built_in">map</span> = <span class="hljs-literal">new</span> HashMap<>();</pre></div><p id="126c">Most likely your IDE is already removing redundant types, or at least you should configure it this way to remove some noise from your code.</p><h1 id="2205">There’s more</h1><p id="f380">Of course there’s more to Java 7 than just these few new language features, <a href="https://openjdk.java.net/projects/jdk7/features/">here’s the overview</a>. We should always thrive to embody changes to our toolchain if they provide us with simpler patterns, new features or better performance. Sometimes it might be even worth to rewrite some code, but don’t force the new stuff on old code if not needed.</p></article></body>

Best of: Java 7

This is the first post of a best of series showcasing the best/new features of programming languages I use. The first one will be Java, starting with version 7, even though Java 13 was just released a few days ago. But much of the Java ecosystem still runs on older versions, and even if you’re not, it’s nice to know about the new features that came with them.

This post was initially released on my blog: https://belief-driven-design.com/2019-09-25/best-of-java-7/

Why Java

Java was never the quickest language in regards of new features compared to newer languages, but IMHO this is one of the reasons why most of the enterprise world still depends on it and will in the future. It’s mostly compatible between versions, long-term-support is good, and there are many options to run it on. Even though some of this changed recently since Java 9 and the new release model

We should always know the complete power of a language we’re using by knowing all the new features and might adapt our coding style. Some things are just syntactic sugar, but other features will help us to reduce and avoid bugs, or get rid of an external-dependency, or even increase performance with a simple code change.

Let’s check out the new features!

The try-with-resources statements

Dealing with I/O was quite cumbersome before Java 7. We have to make sure that resources will be closed eventually, even if an exception occurs, so we end up with a finally block:

BufferedReader reader = new BufferedReader(...);
try {
    reader.readLine();
    ...
}
finally {
    if (reader != null) {
        reader.close();
    }
}

This was a simplified example, maybe we should also check if the reader isn’t already closed?

With Java 7 and the new try-with-resources statement we can streamline this code and make it more readable!

try (BufferedReader reader = new BufferedReader) {
    reader.readLine();
    ...
}

The magic in the background is the new interface java.lang.AutoClosable which allows the automatic closing of resources at the end of the try-with-resources block.

Multiple resources are also supported, they are close in reversed order of declaration:

try (
    BufferedReader reader = new BufferedReader(...);
    BufferedWriter writer = new Files.newBufferedWriter(...)
) {
    ...
}
// After this block first 'writer', then 'reader' will be closed.

The try-with-resources statement is also a normal try-block, so feel free to add catch or finally blocks, they are run after the resources are closed.

Only caveat is exception handling… of course the closing of resources can throw exceptions. But what happens if our code in the try block throws an exception AND the closing of the resource throws another one? In this case Java surpresses the closing exceptions, but they are reachable via #getSurpressed() of the exception, curtosy of java.lang.Throwable.

switch with String literals

Starting with Java 8 the switch statement is capable of handling String literals for its case blocks:

String mode = ...
switch (mode) {
    case "DEV":
        ...
        break;
    case "PROD":
        ...
        break;
    case "QA":
        ...
        break;
    default:
        ...
        break;
}

The comparison is case-sensitive because String#equals is used. switch statements generate more efficient bytecode compared to lots of chained if-then-else.

Binary literal

I don’t work much with binary in my code, but it’s still a nice addition: integral types (byte, short, int, long) are now as easily declarable as hex-number:

// Hex
int asHex = 0x25 // = 35
// NEW: Binary
int asBinary = 0b100011 // = 35

We can either use 0b or 0B as prefix, and might left-pad the value with as many zeros as needed.

The advantage here is that you can better visualize and compare binary variables that might have a direct relationship to another, which wouldn’t be visible in another form of representation.

Improved numeric literals

Numeric literals (including the new binary literal) can now be written in a more comprehensible way, with underscores as separators:

// OLD
long oldCc = 4111111111111111l;
long oldHex = 0xAAFF23C522;
long oldBinary = 0b111000010111;
// NEW 
long cc = 4111_1111_1111_1111l;
long hex = 0xAA_FF_23_C5_22;
long binary = 0b1110_0001_0111;

Some restrictions occur on the placement of the underscore though:

  • not at the beginning or end of a number
  • not adjacent to the decimal point
  • not adjacent to prefixes/suffixes (e.g. 0x, f)

Multiple Exceptions

Instead of multiple catch blocks we can now catch multiple exception types in a single block. It’s nice to have as many different catch blocks as we might need, but if handling them doesn’t differ we combine them with the pipe symbol |:

// OLD
try {
    ...
}
catch (NullPointerException ex) {
    ...
}
catch (IllegalArgumentException ex) {
    ...
}
// NEW
try {
    ...
}
catch (NullPointerException | IllegalArgumentException ex) {
    ...
}

The generated bytecode won’t duplicate any code and will be smaller and more efficient compared to multiple identical catch blocks.

Improved generic type inference for creation

Generics are great except typing so many types:

// OLD
Map<Long, List<String>> map = new HashMap<String, List<String>>();

With Java 7 we don’t need to specify the types on the creation part thanks to the diamond operator: <>:

// NEW
Map<Long, List<String>> map = new HashMap<>();

Most likely your IDE is already removing redundant types, or at least you should configure it this way to remove some noise from your code.

There’s more

Of course there’s more to Java 7 than just these few new language features, here’s the overview. We should always thrive to embody changes to our toolchain if they provide us with simpler patterns, new features or better performance. Sometimes it might be even worth to rewrite some code, but don’t force the new stuff on old code if not needed.

Programming
Java
Jdk
Recommended from ReadMedium