This presentaion provides and overview of the new features of Java 8, namely default methods, functional interfaces, lambdas, method references, streams and Optional vs NullPointerException.
This presentation by Arkadii Tetelman (Lead Software Engineer, GlobalLogic) was delivered at Java.io 3.0 conference in Kharkiv on March 22, 2016.
1. Java 8 intro : Core features
Spring 2016 Arkadii Tetelman
2. 2
Java 8 New Features (Core and Collections)
• Interface’s Default (default methods)
• Functional Interfaces
• Lambdas
• Method References
• Streams (Stream API)
• Optional
3. 3
Interface’s Default (default methods)
Java 8 extends interface declarations with two new items:
• default (default method implementation)
• static methods
• functional interface
4. 4
Default Method
Default methods adds default method implementation that would be used
in the case when the implementer class won’t implement this method .
default is a new keyword in Java8 syntax
When you extend an interface that contains a default method, you can do
the following:
• Not mention the default method at all, which lets your extended interface
inherit the default method.
• Re-declare the default method, which makes it abstract.
• Redefine the default method, which overrides it.
5. 5
Default Method code example
public interface DefaultExample {
default String defaultMethod() {
return "Default implementation";
}
}
private class DefaultableImpl implements DefaultExample {
}
protected abstract class DefaultableAbstractImpl implements DefaultExample {
public abstract String defaultMethod();
}
class OverrideImpl implements DefaultExample {
@Override
public String defaultMethod() {
return "Overridden implementation";
}
}
6. 6
Static Methods in interfaces with example
Another greate feature delivered by Java 8 is that interfaces can declare (and
provide implementation) of static methods. Here is an example:
public interface TimeClient {
static public ZoneId getZoneId (String zoneString) {
try {
return ZoneId.of(zoneString);
} catch (DateTimeException e) {
return ZoneId.systemDefault();
}
}
default public ZonedDateTime getZonedDateTime(String zoneString) {
return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
}
LocalDateTime getLocalDateTime(); // Should be implemented!!!!!!!
}
7. 7
Functional Interfaces
In Java 8 a functional interface is defined as an interface with exactly one abstract method.
New annotation @FunctionalInterface
//Invalid
@FunctionalInterface
public interface SomeInterfaceWithZeroAbstractMethods {}
//Invalid
@FunctionalInterface
public interface SomeInterfaceWithTWOAbstractMethods {
void firstAbstractMethodMethod();
int second(int k);
}
@FunctionalInterface
public interface SomeInterfaceWithONEAbstractMethods {
void f(); // abstract
static int g(int k) {return 0;} // static
default void h() {} // default
}
8. 8
Built-in functional interfaces @ Java 8
Function Method Example
Supplier<T> T get() Supplier<String> stringSupplier = String::new;
String newInteger = stringSupplier.get(); // creates new String
Consumer<T> void accept(T t) List<String> one = Arrays.asList("A","AB","ABA","ABBA");
Consumer<String> style = (String s) ->
System.out.println("Item:"+s);
one.forEach(style);
Predicate<T> boolean test(T t); Predicate<Double> isNegative = x -> x < 0;
System.out.println(isNegative.test(new Double(1)));
Function<T,R> R apply(T t); Function<String, Integer> toInteger = Integer::valueOf;
Integer test = toInteger.apply("2016");
9. 9
Lamdas (Lambda expressions)
A lambda expression (lambda) is a short-form replacement for an anonymous
class. Lambdas simplify the use of interfaces that declare single abstract methods,
that known as functional interfaces.
Core points:
• A lambda expression is a block of code with optional parameters
• Lambda expression is the best choice whenever you want a block of code
executed at a later point in time
• Lambda expression reduces amount of code
• Lambda expression used everywhere in Java8 (StreamAPI, Optionals, etc)
10. 10
Lambda expressions syntax
Lambda Description
() -> 4; takes no value and returns 4;
x -> 3 * x; takes a number and returns the result of
tripling it
(x, y) -> x – y; takes two numbers and returns their
difference
(int x, int y) -> x + y; takes two integers and returns their sum
(String s) -> {
System.out.print("YES"+s);
System.err.print("YES"+s); }
takes a string and prints it to console and
err output with “YES” suffix
New keyword -> (minus with bigger, AKA structure dereference in C++)
(parameters) ->expression
or
(parameters) ->{ statements;}
Lambda Expression and Statements examples:
11. 11
Method References
List<String> one = Arrays.asList("A","AB","ABA","ABBA");
//Reference to a static method
Collections.sort(one, Comparator.comparing((Function<String, Integer>) (s) ->
s.length()));
Collections.sort(one, Comparator.comparing(String::length));
List<String> two = Arrays.asList("1","2","3","4");
//Reference to an instance method of a particular object
two.forEach(System.out::println);
two.forEach((x) -> System.out.println(x));
//Reference to an instance method of an arbitrary object of a particular type
two.forEach(String::toString);
two.forEach((s) -> s.toString());
//Reference to a constructor
List<Integer> integers = two.stream().map(Integer::new).collect(Collectors.toList());
integers = two.stream().map((s) -> new Integer(s)).collect(Collectors.toList());
12. 12
Streams (Stream API)
A newly added Stream API (java.util.stream) introduces real-world
functional-style programming into the Java.
A stream represents a sequence of elements and supports different kind
of operations to perform computations upon those elements.
Stream operations are
• intermediate
• terminal
Intermediate operations return a stream so we can chain multiple
intermediate operations without using semicolons.
Terminal operations are either void or return a non-stream result. In the
above example filter, map and sorted are intermediate operations whereas
forEach is a terminal operation.
For a full list of all available stream operations see the Stream Javadoc.
13. 13
• Streams in Collection with some examples
Streams can be created from various data sources ,especially collections
Kind of Streams:
• stream() – process elements one by one in single thread
• parallelStream() – process elements in several threads
Operation Code Example
Filter
(Intermediate)
stringCollection.stream().filter((s) -> s.startsWith(“A"))
Sorted
(Intermediate)
stringCollection.parallelStream().sorted((a, b) -> b.compareTo(a));
Map
(Intermediate)
stringCollection.stream().map(String::toUpperCase);
Match
(Terminal)
stringCollection.stream().anyMatch((s) -> s.startsWith("a"))
stringCollection.stream().noneMatch((s) -> s.startsWith("z"))
Count
(Terminal)
stringCollection.stream().filter((s) -> s.startsWith(“B")).count();
15. 15
Optional vs NullPointerException
The … NullPointerException is by far the most popular cause of Java
application failures.
Long time ago the great Google Guava project introduced the Optional as
a solution to NullPointerException, discouraging codebase pollution with
null checks and encouraging developers to write cleaner code.
Inspired by Google Guava, the Optional is now a part of Java 8 library
Here is basic example
Optional<String> optional = Optional.of("Some value");
optional.isPresent(); // true
optional.get(); // "Some value"
optional.orElse("fallback"); // "Some value"
optional.ifPresent((s) -> System.out.println(s.charAt(2))); // “m"