One of the most commonly used versions of Java is Java 8 now. We will take a look at some of the features that got introduced in Java 8. We will probably continue with this as a series and take a look at features that got introduced from Java 8 to Java 17, while we wait for the hopeful release of Java 18 this month.
Here is a small list of some of the most used and appreciated features of Java 8.
- Functional Interfaces
- Lambda Expressions
- Default methods and static methods in Interfaces
- ForEach() in Iteratable
- Optional Classes
- Method References
Functional Interface
@FunctionalInterface is used for compiler level errors to enforce contracts of FunctionalInterface. Functional Interface is defined as an interface with a Single Abstract Method(SAM). A typical example is as follows,
@FunctionalInterface
public interface TestInterface{
public void testMtd();
}
Even without the annotation being present this will be considered as a functional interface. Also, any number of default methods in the functional interface. Other than that Object class overriding is not considered an abstract method.
public interface TestInterface{
public void testMtd();
@Override
public String toString();
}
Lambda Expressions
Lambda expressions are anonymous functions(functions with no name and no identifier). They are written inline where they are needed. Lamba expressions are instances of FunctionalInterfaces. Syntax is as follows,
//(parameters) -> expression
(a, b) -> a + b;
//(parameters) -> {statements;}
(a, b) -> {
System.out.println(a);
System.out.println(b);
}
//() -> expressions
() -> System.out.println("Test");
Default methods and static methods in Interfaces
From Java 8, intefaces can be enhaned with default methods and static methods. This allows us to add more functionality to the existing interfaces. One of the implementation is as follows,
default void forEach(Consumer<? Super T action){
Objects.requireNonNull(action);
for(T t: this){
action.accept(t);
}
}
This is the addition of forEach in the Iterable interface.
forEach() in Iteratble
forEach is a function used to iterate over a collection and call a method. It can take a lambda function as an argument.
list.forEach(item -> System.out.println(item));
Optional Classes
Optional classes are used to deal with null pointer exceptions. Optional is added under java.util package and is a public final class. Let's see it working with an example.
Integer a = null;
Optional<Integer> value = Optional.ofNullable(a);
System.out.println(value.isPresent());//false
System.out.println(value.orElse(5));//5
As we saw above, we can check if the value is null or not, set a default value, etc. Let's look at a case where they are not null.
Integer b = 5;
Optional<Integer> value = Optional.of(b);// will throw error if b is null
System.out.println(value.isPresent());//true
System.out.println(value.orElse(6));//5
System.out.println(value.get());//5 (throws error if its null)
Method References
These are shorthand notations for Lambda expressions to call a method. The syntax is quite straightforward.
Object::method
Let's look at a few quick examples as well
//print all elements in a new line
list.forEach(System.out::println);
//sum all integers in a list
int sum = numbers.stream().reduce(0, Integer::sum);
There are a lot more features that got introduced in Java 8 other than the above-mentioned ones. We will revisit them at a later point in time.