avatarBen Weidig

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

6535

Abstract

an class="hljs-literal">null</span>; } <span class="hljs-keyword">return</span> <span class="hljs-keyword">get</span>(<span class="hljs-number">0</span>); }</pre></div><div id="776d"><pre> <span class="hljs-function"><span class="hljs-literal">default</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sort</span>()</span> { <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnsupportedOperationException(); } }</pre></div><p id="18ad">We added 2 new methods that won’t break any existing implementation. They even get an implemented <code>#first()</code> method for free! This is actually the way Java 8 extended a lot of interfaces with new behavior, without breaking everyone’s code.</p><p id="36c1">See <a href="https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html">https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html</a> for more info.</p><h1 id="c925">static interface methods</h1><p id="0195">Another addition to interfaces is the ability to add <code>static</code> methods. It’s a little bit like <code>default</code> methods, but they can’t be overridden.</p><div id="692e"><pre><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-symbol">MyInterface</span> {</pre></div><div id="2fda"><pre> <span class="hljs-type">void</span> <span class="hljs-keyword">add</span>(<span class="hljs-keyword">Object</span> obj); <span class="hljs-keyword">Object</span> <span class="hljs-keyword">get</span>(<span class="hljs-type">int</span> <span class="hljs-keyword">index</span>); <span class="hljs-type">boolean</span> isEmpty();</pre></div><div id="4d1f"><pre> <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printVersion</span>()</span> { System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"0.0.1"</span>); } }</pre></div><h1 id="f751">Lambda expressions and functional interfaces</h1><p id="cd75">One of the greatest additions in my opinion, especially in combination with the new Stream API, are <i>lambda expressions</i>, making the many steps towards a more functional programming style. A <i>lambda expression</i> is a function that lives without an associated class and can be passed around like any other object. To make this possible the concept of <code>functional interfaces</code> was created.</p><p id="22cc">If an interface has only a single abstract method, you can implement it like lambda. This rule can be bend by using <code>default</code> methods, as long as you got only one abstract method.</p><p id="14fe">Interfaces with just one abstract method are automatically <i>functional interfaces</i>, but you might also mark these interfaces with the new annotation <code>@java.lang.FunctionalInterface</code>:</p><div id="18c9"><pre><span class="hljs-meta">@FunctionalInterface</span> <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">MyFunctionalInterface</span> </span>{ <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">method</span><span class="hljs-params">(String arg0)</span></span>; }</pre></div><p id="cd95">Now that we got a functional interface, let’s look at how to use it as a <i>lambda expression</i>. Anonymous classes were the way to go, implementing the abstract methods inline:</p><div id="33e7"><pre><span class="hljs-comment">// OLD</span> <span class="hljs-title class_">MyFunctionalInterface</span> oldWay = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyFunctionalInterface</span>() { <span class="hljs-keyword">public</span> <span class="hljs-title class_">String</span> <span class="hljs-title function_">method</span>(<span class="hljs-params"><span class="hljs-built_in">String</span> arg0</span>) { <span class="hljs-keyword">return</span> <span class="hljs-string">"First argument: "</span> + arg0; } };</pre></div><p id="54ae">Now we can implement a method in a way with less visual noise: <code>(arg0, arg1, ...) -> { return...}</code>. The parenthesis around the arguments are optional if there’s only one argument. And the curly braces and <code>return</code> statement are optional, too, if only a single line of code would occupy the block.</p><div id="ec02"><pre><span class="hljs-comment">// NEW: multiple lines of code</span> MyFunctionalInterface <span class="hljs-keyword">new</span><span class="hljs-type">Way</span> = arg0 -> { <span class="hljs-comment">// ... some other code ...</span> <span class="hljs-keyword">return</span><span class="hljs-string">"First argument: "</span> + arg0); };</pre></div><div id="427a"><pre><span class="hljs-comment">// NEW: only one line of code</span> MyFunctionalInterface <span class="hljs-keyword">new</span><span class="hljs-type">Way</span> = arg0 -> <span class="hljs-string">"First argument: "</span> + arg0;</pre></div><p id="7d58">Especially in combination with <i>streams</i> (a little down this post) or listeners or predicates this will make your code way more readable with less typing:</p><div id="0a37"><pre><span class="hljs-comment">// OLD</span> myEntity.<span class="hljs-title function_">addListener</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">StateListener</span>() { <span class="hljs-keyword">public</span> <span class="hljs-built_in">void</span> <span class="hljs-title function_">onEvent</span>(<span class="hljs-params"><span class="hljs-built_in">String</span> name</span>) { ... } );</pre></div><div id="cd83"><pre><span class="hljs-comment">// NEW</span> <span class="hljs-function"><span class="hljs-title">myEntity</span>.addListener(<span class="hljs-keyword">name</span> -></span> { ... } );</pre></div><p id="374a">See <a href="https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html">https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html</a> for more infos.</p><h1 id="ed6f">Method references</h1><p id="144a">To make lambdas even better you can also use <i>method references</i> which allows us to shortcut method invocations for easier reading your code.</p><p id="59d3">Instead of calling <code>myInstance.method(arg0)</code> you might use <code>myInstance::method</code> if another method expects an l

Options

ambda as argument:</p><div id="48a1"><pre>// <span class="hljs-built_in">OLD</span> <span class="hljs-type">boolean</span> result = list.<span class="hljs-keyword">forEach</span>(o -> myInstance.<span class="hljs-keyword">method</span>(o));</pre></div><div id="c801"><pre><span class="hljs-comment">// NEW</span> boolean <span class="hljs-keyword">result</span> = list.forEach(myInstance::<span class="hljs-keyword">method</span>);</pre></div><p id="b7b8">We can also call instance methods of the incoming parameters directly via the type:</p><div id="2f0b"><pre><span class="hljs-comment">// OLD</span> list.<span class="hljs-title function_ invoke__">stream</span>().<span class="hljs-title function_ invoke__">filter</span>(<span class="hljs-type">str</span> <span class="hljs-punctuation">-></span> <span class="hljs-type">String</span>.<span class="hljs-title function_ invoke__">isEmpty</span>(<span class="hljs-type">str</span>));</pre></div><div id="17e0"><pre><span class="hljs-comment">// NEW</span> list.stream().<span class="hljs-built_in">filter</span>(String::<span class="hljs-built_in">isEmpty</span>);</pre></div><p id="d247">And of course we can use constructors, too, by referencing <code>new</code>:</p><div id="82d6"><pre>list.stream().<span class="hljs-built_in">map</span>(MyEntityClass::<span class="hljs-keyword">new</span>);</pre></div><h1 id="e17e">Java stream API</h1><p id="2eaa">This is the other big thing in this update that makes our Java developer life much easier. The <i>Java Stream API</i> <a href="https://jcp.org/en/jsr/detail?id=335">JSR-335</a> provides a more <i>functional</i> approach to working with <i>streams of data</i>. Streams are designed to work perfectly with <i>lambda expressions/functional interfaces</i> and <i>method references</i>.</p><p id="ebca">We create a stream by calling <code>java.util.Collection#stream()</code> or <code>#parallelStream()</code>, or <code>java.util.stream.Stream.of(...)</code> (a static method on an interface btw), and use the fluent <i>Stream API</i> to process it in a lazy way.</p><p id="c64b">Chaining processing methods like <code>#filter(...)</code> and <code>#map(...)</code> is creating a <i>processing pipeline</i> without actually processing the items while building it, but returning another stream. To actually process your data you must end the fluent call with a so-called <code>terminal-operation</code>. The <i>Stream API</i> is huge and can’t be sufficiently explained in a single blog post, but here are some methods that might interest you:</p><p id="4769"><i>non-terminal-operation</i>:</p><ul><li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#filter-java.util.function.Predicate-">filter</a></li><li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#map-java.util.function.Function-">map</a></li><li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#reduce-U-java.util.function.BiFunction-java.util.function.BinaryOperator-">reduce</a></li><li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#distinct--">distinct</a></li></ul><p id="8688"><i>terminal-operation</i>:</p><ul><li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#collect-java.util.stream.Collector-">collect</a></li><li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#anyMatch-java.util.function.Predicate-">anyMatch</a></li><li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#count--">count</a></li></ul><p id="33f3">I’ve already <a href="https://readmedium.com/java-streams-order-matters-50f010e65e30">written a little bit about streams and order of operations</a> in an earlier blog post.</p><h1 id="0d94">Java Time API</h1><p id="e5b3">Working with dates and time is <a href="https://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time">always cumbersome</a>… the <a href="https://www.joda.org/joda-time/">Joda Time</a> dependency fixed most of the annoyances we usually have while using <code>java.util.Date</code> etc.</p><p id="9cd9">With Java 8 the <code>java.time</code>-package (<a href="https://jcp.org/en/jsr/detail?id=310">JSR-310</a>) was added, which is mostly <i>Joda Time directly in the JDK</i>, so you no longer need an extra dependency for a sensible way to handle date and time.</p><p id="ebdb">Instead of representing date and time with <code>java.util.date</code> we now have a lot of different types in our arsenal to represent the different type of dates and times with or without timezones etc., here are some of them:</p><ul><li><code>java.time.LocalDate</code>: a date without time or time-zone</li><li><code>java.time.LocalDateTime</code>: a date with time but no time-zone</li><li><code>java.time.ZonedDateTime</code>: a date with time and a time-zone</li><li><code>java.time.Duration</code>: a time-based amount of times</li><li><code>java.time.Instant</code>: a single point on a time-line without a time-zone</li></ul><p id="eb68">You find the <a href="https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html">whole list in the documentation</a> and you should really check out some other tutorials and guides about the time API, it will make handling dates and times so much easier!</p><h1 id="5654">Nashorn JavaScript Engine</h1><p id="efcd">A brand-new, implemented from scratch, JavaScript engine called <a href="https://openjdk.java.net/projects/nashorn/"><code>Nash</code>orn</a> was introduced, replacing its predecessor <code>Rhino</code>. This means better ECMAScript support and better performance.</p><div id="7a73"><pre><span class="hljs-built_in">ScriptEngine</span> engine = <span class="hljs-keyword">new</span> <span class="hljs-built_in">ScriptEngine</span>().getEngineByname(<span class="hljs-string">"nashorn"</span>); engine.<span class="hljs-built_in">eval</span>(<span class="hljs-string">"print('Running on nashorn!');"</span>);</pre></div><p id="239a">Don’t celebrate all the JavaScript goodness too early, because Nashorn and its tools <a href="http://openjdk.java.net/jeps/335">are already deprecated with Java 11</a>.</p><h1 id="aad2">There’s a lot more</h1><p id="8b2a">As with my previous post about Java 7 I can’t list all the new features of the release, this was just a quick summary of things I find useful. <a href="https://openjdk.java.net/projects/jdk8/features">Here’s the overview</a> of all new features.</p></article></body>

Best of: Java 8

Photo by Andrew Welch on Unsplash

In the previous part, we looked at version 7 of Java and now it’s time to look at its successor, Java 8, a really big update with lots of great new features! Many of them work in tandem with each other so make sure to check them all out.

Java 8 was a huuuuge release, so lots of topics to cover…

New language features

The general concept of an interface got 2 great enhancements making so much more possible.

default methods on interfaces

I’ve already written about default methods on this blog, but for completion’s sake, I summarize it again here.

One of the big differences between an interface and an abstract class is the ability to actually design a contract (interface) and design a contract and provide a partial implementation (abstract class) of it. The disadvantage of an abstract class lies Java’s single inheritance restriction, so if you want to use a contract with some kind of default implementation AND inherit from another class (abstract or not) you were out of luck… until now!

Interfaces gained the ability to provide default methods, the ability to implement methods directly in the interface without the need to override it later in a class implementing that interface. This way you can provide additional functionality with just implementing an interface yourself. In contrast to an abstract class you can’t use any outside resources (except static ones), no constructors etc. but it will still make it possible to save a lot of code:

// OLD
public interface MyFactory {
    MyEntity build(JSONObject obj);
    List<MyEntity> build(List<JSONObject> objects);
}

In the implementation we might implement the #build(List) method as a simple for-each-loop with some additional null checks, so why not provide this rudimentary functionality directly in the interface instead, so every implementation benefits from it:

// NEW
public interface MyFactory {
    MyEntity build(JSONObject obj);
    default List<MyEntity> build(List<JSONObject> objects) {
        if (objects == null) {
            return null;
        }
        List<MyEntity> result = new ArrayList<>();
        for (JSONObject obj : objects) {
            MyEntity entity = build(obj);
            if (entity != null) {
                result.add(entity);
            }
        }
        return results;
    }
}

Moving the code from the implementation to an interface makes sense if you want to reuse the interface and not just for a 1:1 relationship. This way you provide a senseful default implementation for everyone implementing the interface, and they still can override it if they need another behaviour.

Another great aspect of default methods is the possibility to expand the contract provided by the interface without breaking existing implementations:

public interface List {
    // PREVIOUS METHODS
    void add(Object obj);
    Object get(int index);
    boolean isEmpty();
    // NEW ADDED METHODS
    default Object first() {
        if (isEmpty()) {
            return null;
        }
        return get(0);
    }
    default void sort() {
        throw new UnsupportedOperationException();
    }
}

We added 2 new methods that won’t break any existing implementation. They even get an implemented #first() method for free! This is actually the way Java 8 extended a lot of interfaces with new behavior, without breaking everyone’s code.

See https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html for more info.

static interface methods

Another addition to interfaces is the ability to add static methods. It’s a little bit like default methods, but they can’t be overridden.

public interface MyInterface {
    void add(Object obj);
    Object get(int index);
    boolean isEmpty();
    static void printVersion() {
        System.out.println("0.0.1");
    }
}

Lambda expressions and functional interfaces

One of the greatest additions in my opinion, especially in combination with the new Stream API, are lambda expressions, making the many steps towards a more functional programming style. A lambda expression is a function that lives without an associated class and can be passed around like any other object. To make this possible the concept of functional interfaces was created.

If an interface has only a single abstract method, you can implement it like lambda. This rule can be bend by using default methods, as long as you got only one abstract method.

Interfaces with just one abstract method are automatically functional interfaces, but you might also mark these interfaces with the new annotation @java.lang.FunctionalInterface:

@FunctionalInterface
public interface MyFunctionalInterface {
    void method(String arg0);
}

Now that we got a functional interface, let’s look at how to use it as a lambda expression. Anonymous classes were the way to go, implementing the abstract methods inline:

// OLD
MyFunctionalInterface oldWay = new MyFunctionalInterface() {
    public String method(String arg0) {
        return "First argument: " + arg0;
    }
};

Now we can implement a method in a way with less visual noise: (arg0, arg1, ...) -> { return...}. The parenthesis around the arguments are optional if there’s only one argument. And the curly braces and return statement are optional, too, if only a single line of code would occupy the block.

// NEW: multiple lines of code
MyFunctionalInterface newWay = arg0 -> {
    // ... some other code ...
    return"First argument: " + arg0);
};
// NEW: only one line of code
MyFunctionalInterface newWay = arg0 -> "First argument: " + arg0;

Especially in combination with streams (a little down this post) or listeners or predicates this will make your code way more readable with less typing:

// OLD
myEntity.addListener(new StateListener() {
    public void onEvent(String name) {
        ...
    }
);
// NEW
myEntity.addListener(name -> {
    ...
    }
);

See https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html for more infos.

Method references

To make lambdas even better you can also use method references which allows us to shortcut method invocations for easier reading your code.

Instead of calling myInstance.method(arg0) you might use myInstance::method if another method expects an lambda as argument:

// OLD
boolean result = list.forEach(o -> myInstance.method(o));
// NEW
boolean result = list.forEach(myInstance::method);

We can also call instance methods of the incoming parameters directly via the type:

// OLD
list.stream().filter(str -> String.isEmpty(str));
// NEW
list.stream().filter(String::isEmpty);

And of course we can use constructors, too, by referencing new:

list.stream().map(MyEntityClass::new);

Java stream API

This is the other big thing in this update that makes our Java developer life much easier. The Java Stream API JSR-335 provides a more functional approach to working with streams of data. Streams are designed to work perfectly with lambda expressions/functional interfaces and method references.

We create a stream by calling java.util.Collection#stream() or #parallelStream(), or java.util.stream.Stream.of(...) (a static method on an interface btw), and use the fluent Stream API to process it in a lazy way.

Chaining processing methods like #filter(...) and #map(...) is creating a processing pipeline without actually processing the items while building it, but returning another stream. To actually process your data you must end the fluent call with a so-called terminal-operation. The Stream API is huge and can’t be sufficiently explained in a single blog post, but here are some methods that might interest you:

non-terminal-operation:

terminal-operation:

I’ve already written a little bit about streams and order of operations in an earlier blog post.

Java Time API

Working with dates and time is always cumbersome… the Joda Time dependency fixed most of the annoyances we usually have while using java.util.Date etc.

With Java 8 the java.time-package (JSR-310) was added, which is mostly Joda Time directly in the JDK, so you no longer need an extra dependency for a sensible way to handle date and time.

Instead of representing date and time with java.util.date we now have a lot of different types in our arsenal to represent the different type of dates and times with or without timezones etc., here are some of them:

  • java.time.LocalDate: a date without time or time-zone
  • java.time.LocalDateTime: a date with time but no time-zone
  • java.time.ZonedDateTime: a date with time and a time-zone
  • java.time.Duration: a time-based amount of times
  • java.time.Instant: a single point on a time-line without a time-zone

You find the whole list in the documentation and you should really check out some other tutorials and guides about the time API, it will make handling dates and times so much easier!

Nashorn JavaScript Engine

A brand-new, implemented from scratch, JavaScript engine called Nashorn was introduced, replacing its predecessor Rhino. This means better ECMAScript support and better performance.

ScriptEngine engine = new ScriptEngine().getEngineByname("nashorn");
engine.eval("print('Running on nashorn!');");

Don’t celebrate all the JavaScript goodness too early, because Nashorn and its tools are already deprecated with Java 11.

There’s a lot more

As with my previous post about Java 7 I can’t list all the new features of the release, this was just a quick summary of things I find useful. Here’s the overview of all new features.

Java
Best Practices
Programming
Software Development
Recommended from ReadMedium