Java 10
https://medium.com/@afinlay/java-10-sneak-peek-local-variable-type-inference-var-3022016e1a2b
The use of var also makes your code concise by reducing duplication, e.g. the name of the Class that comes in both right and left-hand side of assignments
http://www.thewindowsclub.com/java-10-new-features
Collections of factory methods
The or() method gives you a fluent way of chaining behaviour on Optionals without checking if the value is present or not.
https://www.pluralsight.com/blog/software-development/java-9-new-features
http://www.baeldung.com/new-java-9
JDK 8
http://winterbe.com/posts/2015/03/15/avoid-null-checks-in-java/
Why Even Use Java 8 Optional?
https://www.voxxed.com/blog/2015/09/java-8-se-optional-a-strict-approach/
Reveal Your Intention
http://www.leveluplunch.com/java/examples/java-util-optional-example/
Java 8 Friday Goodies: Easy-as-Pie Local Caching
http://stackoverflow.com/questions/28840047/recursive-concurrenthashmap-computeifabsent-call-never-terminates-bug-or-fea
we’re using the newly added
Avoid Recursion in ConcurrentHashMap.computeIfAbsent()
http://winterbe.com/posts/2014/03/16/java-8-tutorial/
Default Methods for Interfaces
Java 8 enables us to add non-abstract method implementations to interfaces by utilizing the default keyword. This feature is also known as Extension Methods.
Functional Interfaces
Each lambda corresponds to a given type, specified by an interface. A so called functional interface must contain exactly one abstract method declaration. Each lambda expression of that type will be matched to this abstract method. Since default methods are not abstract you're free to add default methods to your functional interface.
map.putIfAbsent(i, "val" + i);
map.computeIfPresent(3, (num, val) -> val + num);
how to remove entries for a a given key, only if it's currently mapped to a given value:
map.remove(3, "val3");
map.get(3); // val33
map.merge(9, "val9", (value, newValue) -> value.concat(newValue));
Annotations in Java 8 are repeatable.
@interface Hints {
Hint[] value();
}
@Repeatable(Hints.class)
@interface Hint {
String value();
}
Variant 2: Using repeatable annotations (new school)
@Hint("hint1")
@Hint("hint2")
class Person {}
Using variant 2 the java compiler implicitly sets up the @Hints annotation under the hood. That's important for reading annotation informations via reflection.
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
@interface MyAnnotation {}
JDK 9
http://blog.takipi.com/5-features-in-java-9-that-will-change-how-you-develop-software-and-2-that-wont/
1. Java + REPL = jshell
2. Microbenchmarks are coming
3. Will G1 be the new default garbage collector?
4. HTTP 2.0 is the future
5. The process API just got a huge boost
http://blog.takipi.com/java-9-early-access-a-hands-on-session-with-jshell-the-java-repl/
http://www.infoq.com/articles/Java9-New-HTTP-2-and-REPL
The existing version, HTTP/1.1, dates from 1999 and has significant problems, including:
Head-of-line blocking
In HTTP/1.1 responses are received in the same order as the requests were sent. This means that, for example, when viewing a large HTML page containing several small images, the images will have to "queue up" behind the HTML and can’t be sent until the browser finishes completely downloading the HTML. This is called "Head-of-line blocking" and leads to a number of possible rendering problems.
In HTTP/2, responses can be chunked and even interleaved, to allow responses and requests to be truly multiplexed.
Restricted connections to a single site
Overhead of control headers
The alternative is to use a binary encoding for headers. This approach can greatly speed up smaller requests and uses far less bandwidth. It is the approach that HTTP/2 has chosen to follow, in the spirit of the principle that standards should prefer text-based protocols, but use binary for efficiency where compelling reasons to do so exist.
https://dzone.com/articles/will-there-be-module-hell
JAR Hell:
https://medium.com/@afinlay/java-10-sneak-peek-local-variable-type-inference-var-3022016e1a2b
2) You cannot instantiate multiple variables either
var x=0,y=0; // no!
3) No Lambdas, Method References, or Array Initializers
4) No null values!
var x = null; //No! var y = funcReturningNull(); //No!
// We cannot infer the type.
5) You cannot reassign to a different type
var x=0; //Inferred to be of type 'int' var x="c"; //No! - incompatible types!https://dzone.com/articles/finally-java-10-has-var-to-declare-local-variables
The use of var also makes your code concise by reducing duplication, e.g. the name of the Class that comes in both right and left-hand side of assignments
var bos = new ByteArrayOutputStream();
try (var books = dbconn.executeQuery(query)) {
return books.map(...)
.filter(...)
.findAny();
}
Anyway, the local variable type inference of Java 10's var keyword can only be used to declare local variables, e.g. any variable inside a method body or code block.
You cannot use var to declare member variables inside the class, formal parameters, or to return the type of methods.
- One important thing to know is that even though var looks like a keyword, it's not really a keyword. Instead, it is a reserved type name. This means that code that uses var as a variable, method, or package name will not be affected.
// none of this works
var ints = {0, 1, 2};
var appendSpace = a -> a + " ";
var compareString = String::compareTo
|
The only other eligible spots besides local variables are for loops and try-with-resources blocks:
// var in for loops
var numbers = List.of("a", "b", "c");
for (var nr : numbers)
System.out.print(nr + " ");
for (var i = 0; i < numbers.size(); i++)
System.out.print(numbers.get(i) + " ");
// var in try-with-resources
try (var file = new FileInputStream(new File("no-such-file"))) {
new BufferedReader(new InputStreamReader(file))
.lines()
.forEach(System.out::println);
} catch (IOException ex) {
// at least, we tried
System.out.println("There's actually no `no-such-file`. :)");
}
|
Avoiding “Action At A Distance” Errors
That var can only be used locally is not a technical limitation, but a design decision. Sure, it would be nice to have it work like this:
// cross fingers that compiler infers List<User>
var users = new ArrayList<User>();
// but it doesn't, so this is a compile error:
users = new LinkedList<>();
|
The compiler could easily look at all assignments and infer the most concrete type that fits all of them, but it doesn’t. The JDK team wanted to avoid “action at a distance” errors, meaning changing code in some place should not lead to a seemingly unrelated error far away.
https://www.journaldev.com/20395/java-10-featuresLocal-Variable Type Inference
- Limited only to Local Variable with initializer
- Indexes of enhanced for loop or indexes
- Local declared in for loop
var numbers = List.of(1, 2, 3, 4, 5); // inferred value ArrayList<String> // Index of Enhanced For Loop for (var number : numbers) { System.out.println(number); } // Local variable declared in a loop for (var i = 0; i < numbers.size(); i++) { System.out.println(numbers.get(i)); }
- List, Map & Set Interfaces are added with a static copyOf(Collection) method. Its returns an unmodifiable List, Map or Set containing the entries provided. For a List, if the given List is subsequently modified, the returned List will not reflect such modifications.
- Optional & its primitive variations get a method orElseThrow(). This is exactly same as get(), however the java doc states that it is a preferred alternative then get()
- Collectors class gets various methods for collecting unmodifiable collections (Set, List, Map)
List<String> actors = new ArrayList<>(); actors.add("Jack Nicholson"); actors.add("Marlon Brando"); System.out.println(actors); // prints [Jack Nicholson, Marlon Brando] // New API added - Creates an UnModifiable List from a List. List<String> copyOfActors = List.copyOf(actors); System.out.println(copyOfActors); // prints [Jack Nicholson, Marlon Brando] // copyOfActors.add("Robert De Niro"); Will generate an // UnsupportedOperationException actors.add("Robert De Niro"); System.out.println(actors);// prints [Jack Nicholson, Marlon Brando, Robert De Niro] System.out.println(copyOfActors); // prints [Jack Nicholson, Marlon Brando] String str = ""; Optional<String> name = Optional.ofNullable(str); // New API added - is preferred option then get() method name.orElseThrow(); // same as name.get() // New API added - Collectors.toUnmodifiableList List<String> collect = actors.stream().collect(Collectors.toUnmodifiableList()); // collect.add("Tom Hanks"); // Will generate an // UnsupportedOperationException
http://www.thewindowsclub.com/java-10-new-features
- Docker awareness – Beginning now, in any instance where you chose to run Java 10 on Linux systems, the Java Virtual Machine (JVM) will quickly recognize if it is running in a Docker container. Container-specific information like the number of CPUs and total memory allocated to the container will be extracted by the JVM instead of it querying the operating system.
Collections of factory methods
jshell> List.of(1, 2, 3)
$1 ==> [1, 2, 3]
jshell> Set.of(1, 2)
$2 ==> [2, 1]
jshell> Map.of("hello", "world")
The resulting objects are immutable collections that are optimised for performance. For example, a singleton list, with just 1 element holds the item in a field to speed up accessing the value.
jshell> List.of(1).getClass()
$4 ==> class java.util.ImmutableCollections$List1
In particular, the dropWhile and takeWhile methods. These behave quite predictably: dropWhile discards the first items of the stream until a condition is met, takeWhile processes items until a condition is met.
jshell> IntStream.range(1, 10).dropWhile(x -> x < 5).forEach(System.out::println)
5
Iterate allows you to write proper replacements for the for loops using streams. It takes the initial value of the stream, the condition that defines when to stop iterating and the step function to produce the next element.
IntStream.iterate(0, x -> x < 3, x -> x + 1).forEach(System.out::println)
0
1
2
jshell> Optional.empty().or(() -> Optional.of("RebelLabs"))
$5 ==> Optional[RebelLabs]
convert an Optional into a Stream containing at most one element. It’s really useful if you want to use the laziness of the Streams API. Check out the difference in the examples below. Calling map() on the Optional executes the mapping function immediately, on the Stream — not.
jshell> Optional.of(1).map(x -> x * 3)
$10 ==> Optional[3]
jshell> Optional.of(1).stream().map(x -> x * 3)
$11 ==> java.util.stream.ReferencePipeline$3@67b92f0a
Optional addition we want to talk about is the ifPresentOrElse method. In Java 8, you could specify the behaviour you want to execute if the value in an Optional is present. In Java 9 you can pass 2 Runnables to specify what to do if the value is present and otherwise.
jshell> Optional.empty().ifPresentOrElse(x -> System.out.println(x), () -> System.out.println("empty"));
empty
jshell> CompletableFuture<String> future = new CompletableFuture<>()
future ==> java.util.concurrent.CompletableFuture@35d176f7[Not completed]
jshell> future.copy()
$15 ==> java.util.concurrent.CompletableFuture@4973813a[Not completed]
jshell> future.isDone()
$17 ==> false
jshell> $15.isDone()
$18 ==> false
jshell> $15.complete("JRebel")
In Java 9 it’s quite straightforward. Java 9 adds the ProcessHandle class, which offers an API to inspect the current process, processes found by their PID, their children processes and so on. Check out the snippet below.
jshell> ProcessHandle current = ProcessHandle.current();
current ==> 6349
jshell> current.pid()
$33 ==> 6349
jshell> current.info().\TAB
arguments() command() commandLine() equals( getClass()
hashCode() notify() notifyAll() startInstant() toString()
totalCpuDuration() user() wait(
jshell> current.info().command()
Another very common task that will be easier with Java 9 is executing code when a certain process finishes. Java 9 adds
CompletableFuture<Process> onExit()
The reason for that is that in the future, the underscore will possibly be used for the function parameters you don’t care about.
Interfaces also got a revamp. In Java 9 interfaces can contain private methods. The default methods in interfaces made Java 8 interfaces able to contain the common functionality. Now you can also use private methods to extract common functionality from inside an interface without creating utility classes.
The last addition we want to talk about is using the effectively final variables in the try-with-resources blocks. It simplifies the code, you don’t need to declare the variable in the try statement. You can just use the variables that are effectively final and just reference them in the try block.
boolean a() throws Exception {
Socket s = new Socket();
try (s) { }
return s.isClosed();
}
7. Private interface methods
he new HttpClient API is delivered as a so-called _incubator module_ in Java 9. This means the API isn't guaranteed to be 100% final yet
HttpClient client = HttpClient.newHttpClient();
HttpRequest req =
HttpRequest.newBuilder(URI.create("http://www.google.com"))
.header("User-Agent","Java")
.GET()
.build();
HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandler.asString());
9. Multi-release JARs
The last feature we're highlighting is especially good news for library maintainers. When a new version of Java comes out, it takes years for all users of your library to switch to this new version. That means the library has to be backward compatible with the oldest version of Java you want to support (e.g., Java 6 or 7 in many cases). That effectively means you won't get to use the new features of Java 9 in your library for a long time
https://www.journaldev.com/13121/java-9-features-with-exampleshttp://www.baeldung.com/new-java-9
let’s stop all the running child processes using destroy():
1
2
3
4
| childProc = ProcessHandle.current().children(); childProc.forEach(procHandle -> { assertTrue( "Could not kill process " + procHandle.getPid(), procHandle.destroy()); }); |
Now we can use diamond operator in conjunction with anonymous inner classes:
1
2
3
4
5
6
7
8
9
| FooClass<Integer> fc = new FooClass<>( 1 ) { // anonymous inner class }; FooClass<? extends Integer> fc0 = new FooClass<>( 1 ) { // anonymous inner class }; FooClass<?> fc1 = new FooClass<>( 1 ) { // anonymous inner class }; |
http://winterbe.com/posts/2015/03/15/avoid-null-checks-in-java/
Resolving a deep nested path in this structure can be kinda awkward. We have to write a bunch of null checks to make sure not to raise a
NullPointerException
:
We can get rid of all those null checks by utilizing the Java 8
Optional
type. The method map
accepts a lambda expression of type Function
and automatically wraps each function result into an Optional
. That enables us to pipe multiple map
operations in a row. Null checks are automatically handled under the hood.
An alternative way to achieve the same behavior is by utilizing a supplier function to resolve the nested path:
Calling
obj.getNested().getInner().getFoo())
might throw a NullPointerException
. In this case the exception will be caught and the method returns Optional.empty()
.Why Even Use Java 8 Optional?
https://www.voxxed.com/blog/2015/09/java-8-se-optional-a-strict-approach/
Reveal Your Intention
Additionally, this intention can be automatically checked with tools like FindBugs:
// an empty 'Optional';
// before Java 8 you would simply use a null reference here
Optional<String> empty = Optional.empty();
// an 'Optional' where you know that it will not contain null;
// (if the parameter for 'of' is null, a 'NullPointerException' is thrown)
Optional<String> full = Optional.of(
"Some String"
);
// an 'Optional' where you don't know whether it will contain null or not
Optional<String> halfFull = Optional.ofNullable(someOtherString);
optionalFramework.orElseThrow(IllegalStateException::new);
optionalFramework.ifPresent(p -> System.out.println(p.name));
Java 8 Friday Goodies: Easy-as-Pie Local Caching
http://stackoverflow.com/questions/28840047/recursive-concurrenthashmap-computeifabsent-call-never-terminates-bug-or-fea
we’re using the newly added
Map.computeIfAbsent()
method to calculate a new value from a source
function only if we don’t already have a value for a given key. static Map<Integer, Integer> cache = new ConcurrentHashMap<>();
static
int
fibonacci(
int
i) {
if
(i ==
0
)
return
i;
if
(i ==
1
)
return
1
;
return
cache.computeIfAbsent(i, (key) -> {
System.out.println(
"Slow calculation of "
+ key);
return
fibonacci(i -
2
) + fibonacci(i -
1
);
});
}
If the specified key is not already associated with a value, attempts to compute its value using the given mapping function and enters it into this map unless null. The entire method invocation is performed atomically, so the function is applied at most once per key. Some attempted update operations on this map by other threads may be blocked while computation is in progress, so the computation should be short and simple, and must not attempt to update any other mappings of this map.
The “must not” wording is a clear contract, which my algorithm violated, although not for the same concurrency reasons.
IllegalStateException – if the computation detectably attempts a recursive update to this map that would otherwise never complete
But that exception isn’t thrown. Neither is there any ConcurrentModificationException. Instead, the program just never halts.
The simplest use-site solution for this concrete problem would be to not use a ConcurrentHashMap, but just a HashMap instead:
1
| static Map<Integer, Integer> cache = new HashMap<>(); |
Subtypes overriding super type contracts
The
HashMap.computeIfAbsent()
or Map.computeIfAbsent()
Javadoc don’t forbid such recursive computation, which is of course ridiculous as the type of the cache is Map<Integer, Integer>
, not ConcurrentHashMap<Integer, Integer>
. It is very dangerous for subtypes to drastically re-define super type contracts (Set
vs. SortedSet
is greeting). It should thus be forbidden also in super types, to perform such recursion.Default Methods for Interfaces
Java 8 enables us to add non-abstract method implementations to interfaces by utilizing the default keyword. This feature is also known as Extension Methods.
interface Formula {
double calculate(int a);
default double sqrt(int a) {
return Math.sqrt(a);
}
}
Lambda
Collections.sort(names, (String a, String b) -> {
return b.compareTo(a);
});
As you can see the code is much shorter and easier to read. But it gets even shorter:
Collections.sort(names, (String a, String b) -> b.compareTo(a));
For one line method bodies you can skip both the braces
{}
and the return
keyword. But it gets even more shorter:Collections.sort(names, (a, b) -> b.compareTo(a));
personList.sort((p1, p2) -> p1.firstName.compareTo(p2.firstName));
java.util.Optional<Employee> employee = employees
.stream()
.sorted((e1, e2) -> e1.getHireDate()
.compareTo(e2.getHireDate())).findFirst();
The java compiler is aware of the parameter types so you can skip them as well.
Each lambda corresponds to a given type, specified by an interface. A so called functional interface must contain exactly one abstract method declaration. Each lambda expression of that type will be matched to this abstract method. Since default methods are not abstract you're free to add default methods to your functional interface.
@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}
Method and Constructor References
Java 8 enables you to pass references of methods or constructors via the
::
keyword.Converter<String, Integer> converter = Integer::valueOf;
Integer converted = converter.convert("123");
Something something = new Something();
Converter<String, String> converter = something::startsWith;
String converted = converter.convert("Java");
PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.create("Peter", "Parker");
Lambda Scopes
Accessing outer scope variables from lambda expressions is very similar to anonymous objects. You can access final variables from the local outer scope as well as instance fields and static variables.
However num must be implicitly final for the code to compile. The following code does not compile:
int num = 1;
Converter<Integer, String> stringConverter =
(from) -> String.valueOf(from + num);
num = 3;
Accessing fields and static variables
Default methods cannot be accessed from within lambda expressions.
map.putIfAbsent(i, "val" + i);
map.computeIfPresent(3, (num, val) -> val + num);
how to remove entries for a a given key, only if it's currently mapped to a given value:
map.remove(3, "val3");
map.get(3); // val33
map.merge(9, "val9", (value, newValue) -> value.concat(newValue));
Annotations in Java 8 are repeatable.
@interface Hints {
Hint[] value();
}
@Repeatable(Hints.class)
@interface Hint {
String value();
}
Variant 2: Using repeatable annotations (new school)
@Hint("hint1")
@Hint("hint2")
class Person {}
Using variant 2 the java compiler implicitly sets up the @Hints annotation under the hood. That's important for reading annotation informations via reflection.
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
@interface MyAnnotation {}
JDK 9
http://blog.takipi.com/5-features-in-java-9-that-will-change-how-you-develop-software-and-2-that-wont/
1. Java + REPL = jshell
2. Microbenchmarks are coming
3. Will G1 be the new default garbage collector?
4. HTTP 2.0 is the future
5. The process API just got a huge boost
http://blog.takipi.com/java-9-early-access-a-hands-on-session-with-jshell-the-java-repl/
http://www.infoq.com/articles/Java9-New-HTTP-2-and-REPL
The existing version, HTTP/1.1, dates from 1999 and has significant problems, including:
Head-of-line blocking
In HTTP/1.1 responses are received in the same order as the requests were sent. This means that, for example, when viewing a large HTML page containing several small images, the images will have to "queue up" behind the HTML and can’t be sent until the browser finishes completely downloading the HTML. This is called "Head-of-line blocking" and leads to a number of possible rendering problems.
In HTTP/2, responses can be chunked and even interleaved, to allow responses and requests to be truly multiplexed.
Restricted connections to a single site
Overhead of control headers
The alternative is to use a binary encoding for headers. This approach can greatly speed up smaller requests and uses far less bandwidth. It is the approach that HTTP/2 has chosen to follow, in the spirit of the principle that standards should prefer text-based protocols, but use binary for efficiency where compelling reasons to do so exist.
https://dzone.com/articles/will-there-be-module-hell
JAR Hell:
- Unexpressed and transitive dependencies
- Shadowing
- Version conflicts
- Complex class loading