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.
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>
varusers=newArrayList<User>();
// but it doesn't, so this is a compile error:
users=newLinkedList<>();
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.
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
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.
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.
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
The or() method gives you a fluent way of chaining behaviour on Optionals without checking if the value is present or not.
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.
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.
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.
booleana()throws Exception {
Socket s = new Socket();
try (s) { }
return s.isClosed();
}
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
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 mapaccepts 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.
Calling obj.getNested().getInner().getFoo()) might throw a NullPointerException. In this case the exception will be caught and the method returns Optional.empty().
publicstatic<T> Optional<T>resolve(Supplier<T> resolver){try{
T result = resolver.get();return Optional.ofNullable(result);}catch(NullPointerException e){return Optional.empty();}}
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:
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.
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.
The java compiler is aware of the parameter types so you can skip them as well.
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.
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:
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.
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.