From java 8 to java 11 in single step

Giacomo Veneri
digitalindustry
Published in
7 min readApr 8, 2019

imported from http://jugsi.blogspot.com/2018/11/from-java-8-to-java-11-in-single-step.html

I have been working with Java 8 for 4 years, then I decided to move to LTS (long term support) Java 11 released on October 2018. My question is “what I have to learn about APIs?”

We know the story about the

… supported new Garbage Collectors (ZGJ and Epsilon) and Modularity.

We know the feature about

JShell and TLS 1.3

support. Finally, maybe we do not know about the

… support for “shebang” Java files! #!/bin/java

Maybe we should know about the

… support for container

Source: oracle
Next …

How about APIs?

APIs and Syntax from 8 to 11

I started my investigation about the gap to cover from there https://codete.com/blog/java-8-java-11-quick-guide/ .

Variable

From Java 10, developers can choose to let the compiler infer types by using var.

Java 10

var x=1.0/2.0var list = new ArrayList<String>();  var stream = list.stream();// Type inference can be (Java 8)
Function helloFunction = s -> "Hello " + s;

// Inference of generics (Diamond Operator, since Java 7)
List strings = new ArrayList<>();
strings.add(helloFunction.apply("World"));

// Inference of generics (Diamond Operator) with anonymous inner classes (Java 9 -> JEP 213)
Consumer printer = new Consumer<>() {
@Override
public void accept(String string) {
System.out.println(string);
}
};
strings.forEach(printer::accept);

Java 11

Java 11 has improved the “var” for lambda:

IntFunction<Integer> doubleIt1 = (int x) -> x * 2; // OK Java 10 and 11
IntFunction<Integer> doubleIt2 = (var x) -> x * 2; // OK Java 11

and more:

// A look at Java 11 (JEP 323)
/ Inference of parameters in Lambda expressions
Consumer<String> printer = (var s) -> System.out.println(s); // statt s -> System.out.println(s);

// But no mixture of "var" and declarated types possible
// BiConsumer<String, String> printer = (var s1, String s2) -> System.out.println(s1 + " " + s2);

// Useful for type annotations
BiConsumer<String, String> printer = (@Nonnull var s1, @Nullable var s2) -> System.out.println(s1 + (s2 == null ? "" : " " + s2));
// given
Optional<String> value = Optional.of("properValue");
AtomicInteger successCounter = new AtomicInteger(0);

AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);

// when
value.ifPresentOrElse(
v -> successCounter.incrementAndGet(),
onEmptyOptionalCounter::incrementAndGet);

String new methods

Java 8

The new join method on Java 8

Set<String> set1 = Set.of("a","b", "c");
List<String> list1 = List.of("a","b", "c");

System.out.println( String.join("a", "b", "c") );
System.out.println( String.join(".", set1) );
System.out.println( String.join(".", list1) );

Java 9

In java 9 we have new method to return Stream

Java 11

String.repeat(int)
String.lines()
String.strip()
String.stripLeading()
String.stripTrailing()
String.isBlank()

Interface

Java 8

  1. Constant variables
  2. Abstract methods
  3. Default methods
  4. Static methods

Java 9

  1. Constant variables
  2. Abstract methods
  3. Default methods
  4. Static methods
  5. Private methods
  6. Private Static methods

Java 11

Now a complete example:

//generic interface with one type parameter T
interface SomeInterface<T> {
int SOME_CONSTANT = 35; // variable declaration
int abstractMethod(int x, int y); // method declaration
T abstractMethodUsingGenericType(T[] array, int i); // method using type parameter
default int defaultMethod(int x, int y) {
// implementation of method
return 0;
}
static void main(String[] args) {
// any static method, including main can be included in interface
}


private void privateMethod(String[] args) {
// any private method can be included in interface
}

private static void staticMethod(String[] args) {
// any private static method can be included in interface
}

// nested class definition
class NestedClass {
// members of a class
}
// nested interface definition
interface NestedInterface {
// member of an interface
}
// nested enum definition
enum NestedEnum {
OBJECT1,
OBJECT2,
;
// methods, variables and constructors
}
// nested annotation definition
@interface NestedAnnotation {
String attrib1();
}
}

Nullable Management

Java 8

Java 8 has introduced the new “Optional” keyword (see also https://homes.cs.washington.edu/~mernst/advice/nothing-is-better-than-optional.html):

// return an optional empty object
Optional<String> optional = Optional.empty();
// return an optional with value object
String str = "value";
Optional<String> optional = Optional.of(str);
// return an optional with or without value
Optional<String> optional = Optional.ofNullable(getString());
// how to solve String version = computer?.getSoundcard()?.getUSB()?.getVersion() ?: "UNKNOWN";// with mapString version = computer.flatMap(Computer::getSoundcard)
.flatMap(Soundcard::getUSB)
.map(USB::getVersion)
.orElse("UNKNOWN");
//listList<String> list = getList();
List<String> listOpt = list != null ? list : new ArrayList<>();
// is equivalent to
List<String> listOpt = getList().orElseGet(() -> new ArrayList<>());

Java 9

In Java 9 Optional has been enhanced to return another Optional and enhanced with the method ifPresentOrElse :

// given
String defaultString = "default";
Optional<String> value = Optional.empty();
Optional<String> defaultValue = Optional.of(defaultString);
// when
Optional<String> result = value.or(() -> defaultValue);
// given
Optional<String> value = Optional.of("properValue");
AtomicInteger successCounter = new AtomicInteger(0);

AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);

// when
value.ifPresentOrElse(
v -> successCounter.incrementAndGet(),
onEmptyOptionalCounter::incrementAndGet);

The Optional has been enhanced also with the stream method.

Java 10

On Java 10 Optional has a new method called “orElseThrow”.

Java 11

Optional.of(string).isEmpty()

see also https://dzone.com/articles/90-new-features-and-apis-in-jdk-11

Stream

Java 8

Java 8 ha introduced the new “Stream” idea : https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html

// starting from list
List<String> myList =
Arrays.asList("a1", "a2", "b1", "c2", "c1");
myList
.stream()
.filter(s -> s.startsWith("c"))
.map(String::toUpperCase)
.sorted()
.forEach(System.out::println);
// native stream
Stream.of("a1", "a2", "a3")
.findFirst()
.ifPresent(System.out::println);

working with number and map (source: https://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/)

// working with number
IntStream.range(1, 4)
.forEach(System.out::println);
// working with map
Arrays.stream(new int[] {1, 2, 3})
.map(n -> 2 * n + 1)
.average()
.ifPresent(System.out::println);

and the stream supplier to reuse the stream several time and avoid the famous

java.lang.IllegalStateException: stream has already been operated upon or closed

Supplier<Stream<String>> streamSupplier =
() -> Stream.of("d2", "a2", "b1", "b3", "c")
.filter(s -> s.startsWith("a"));
streamSupplier.get().anyMatch(s -> true); // ok
streamSupplier.get().noneMatch(s -> true); // ok

The collector to transform on several list:

List<Person> filtered =
persons
.stream()
.filter(p -> p.name.startsWith("P"))
.collect(Collectors.toList());

Managing nullability with flatMap

Outer outer = new Outer();if (outer != null && outer.nested != null && outer.nested.inner != null) {
System.out.println(outer.nested.inner.foo);
}
// similar to
Optional.of(new Outer())
.flatMap(o -> Optional.ofNullable(o.nested))
.flatMap(n -> Optional.ofNullable(n.inner))
.flatMap(i -> Optional.ofNullable(i.foo))
.ifPresent(System.out::println);

Se also differences between map and flatMap https://www.baeldung.com/java-difference-map-and-flatmap

Java 9

On Java 9 the iterate and takeWhile/dropWhile method have been introduced.

Stream.iterate(0, i -> i < 10, i -> i + 1) .forEach(System.out::println);
System.out.println("stream take while");
Stream<String> stream1 = Stream.iterate("", s -> s + "s")
.takeWhile(s -> s.length() < 10);

stream1.forEach(System.out::println);

Java 11

New predicate with not

lines.stream()          
.filter(s -> !s.isBlank())

now is

lines.stream()          
.filter(Predicate.not(String::isBlank))

Reactive Streams

Java 9

From java 9 java.util.concurrent.Flow encloses the following 4 interfaces

  • Flow.Processor
  • Flow.Publisher
  • Flow.Subscriber
  • Flow.Subscription

Utils

Immutable collections are the new features introduced on java 8 and enhanced on java 9

Java 9

// empty immutable collections
List<String> emptyImmutableList = List.of();
Set<String> emptyImmutableSet = Set.of();
Map emptyImmutableMap = Map.of();
// immutable collections
List<String> immutableList = List.of("one", "two");
Set<String> immutableSet = Set.of("value1", "value2");
Map<String, String> immutableMap = Map.of("key1", "Value1", "key2", "Value2", "key3", "Value3");

Java 9 has also introduce the support for MultiResolutionImage.

Java 9 has also improved the Process api.

Java 10

Additionally, API for creating unmodifiable collections has been improved by adding List.copyOf(), Set.copyOf(), Map.copyOf() methods, which are factory methods for creating unmodifiable instances from existing collections. Also, Collectors class has some new methods like toUnmodifiableList, toUnmodifiableSet, toUnmodifiableMap.

New Syntax

Java 9 try-with-resource now support inner aucloseable

try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) {
// do some stuff with finalCloseable
} catch (Exception ex) { }

Java 9 supports also the anonymous class with diamond operator

List<String> list = new ArrayList<>(){ };

Java 9 supports the new HTTP client API which supports HTTP/2 and websockets (https://dzone.com/articles/an-introduction-to-http2-support-in-java-9)

Java 11 improved the support for HTTP client API (https://hackernoon.com/javahttp2-3a9b398c826d)

Java (11+) 12 switch will be very simple (https://openjdk.java.net/jeps/325)

int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};

Lambdas

Lambdas have been introduced on Java 8 the basic syntax of Lambdas is

s -> do(s)

To support lambdas java 8 has introduced 5 new different interface

Consumer, Function, Supplier, Predicate, Operator

and several methods on Iterable & Stream & Optional:

  • forEach
  • filter
  • map
  • flatMap
  • collect

on Java 11 has improved the java lambdas support with “var” inferencing.

Deprecated

Java 9 short list (https://docs.oracle.com/javase/9/docs/api/deprecated-list.html)

  1. java.activation
  2. java.corba
  3. java.se.ee
  4. java.transaction
  5. java.xml.bind
  6. java.xml.ws
  7. java.xml.ws.annotation
  8. jdk.policytool

Java 11 short list

Java EE packages removed

  • javax.activation (java.activation)
  • javax.activity, javax.rmi, javax.rmi.CORBA, org.omg.* (java.corba)
  • javax.transaction (java.transaction)
  • javax.xml.bind.* (java.xml.bind)
  • javax.jws, javax.jws.soap, javax.xml.soap, javax.xml.ws.*(java.xml.ws)
  • javax.annotation (java.xml.ws.annotation)

Logging

Java 9
new unified logging capability providing level, scope (gc, out, err,), what and destination

eg.

java -Xlog:all=debug:file=application.log -version

See also https://www.baeldung.com/java-9-logging-api

http://openjdk.java.net/jeps/158

Annotations

Java 8

  • @FunctionalInterface : to specify an interface “for lambda” purpose

Java 9

has improved the following annotations

--

--