This post will detail some of the new features found in Java 8. It will be broken up into multiple posts. The first post will be around functional interfaces and lambdas. The other posts will focus on the new Streams API, and a new API for Date and Time.

Some say Java 8 is the best thing since sliced bread. Whether that is true or not is yet to be determined, but it does seem to have some of the most new features since Java 5. This won’t be a post on Functional Programming, as that could be a separate post on its own, but it may help if you are familiar with it.

Functional Interfaces

One of the new features in Java 8 is a Functional Interface. A Functional Interface is an interface that defines a single method, that is not a default method. A default method is an default implementation of a method. Yes, interfaces can now implement default methods like an abstract class!

Example,

public interface IManager {

	void method1();

	default void method2() { System.out.println("method2");}

}

This interface is a Functional Interface because it defines a single method method1, that is not a default method.

To declare an interface as a Functional Interface, simply add the @FunctionalInterface annotation.

Common functional interfaces

public interface Predicate<T> { boolean test(T t); }

public interface Command  { void execute(); }

public interface BinaryOperator<T> { T op(T x, T y); }

public interface BiFunction<T, U, R> { R apply(T t, U u); }

Java 8’s new package java.util.Function provides many of these new interfaces and is worth checking out.

So why is this important? There are two reasons, one is that now this gives a way for classes to mimic multiple inheritance. The other is that Functional Interfaces can be used as Lambda expressions.

Multiple Inheritance

For example, class Test does not have to implement method1 or method2, they are both provided, hence a form of multiple inheritance.

public interface ITest1 { 
	default void method1() { 
		System.out.println("method1");}
	}

public interface ITest2 { 
	default void method2() { 
		System.out.println("method2");}
	}


public class Test implements ITest1,ITest2 {
	//I don't have to implement method1 or method2		
}

Lambdas

One of the main new features in Java 8 is Lambdas. Well, it’s actually not new, it’s been around in Java in the form of anonymous inner classes. However, there is a nicer way to apply them than before. Instead of passing an object that implements an interface, we can now pass blocks of code. We do this through Lambda expressions, which are in the form of (parameters) -> {body}.

Example,

Take this interface, public interface Runnable { void run(); }

Previously, to create a new thread with a Runnable object, the code would look like:

Runnable oldStatement = new Runnable() {

	@Override
	public void run() {			
		System.out.println("doing something");
	}

};
Thread t = new Thread(oldStatement);

Using Lambda expressions, we can create a Runnable like this:

Runnable multiStatement = () -> {
	System.out.println("task1");
};

In Fact, you can even declare it inline as so:

Thread t2 = new Thread(() -> {System.out.println("do something");});

Since the run method takes no parameters, the section before the -> is an empty list ().

I can do the above because Runnable is a functional interface. Since Runnable has only one method, Java can determine which method to apply the code to after the ->. Here are the class contents.

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

An example that includes parameters would be to use the BinaryOperator interface.

public interface BinaryOperator<T> { T op(T x, T y); }

We could use that to add to Longs together like so:

BinaryOperator<Long> bo = (x,y) ->  x + y;

Now you can use the function as System.out.println(bo.apply(3l,4l));

Conclusion

Hopefully this was an informative intro into some of the new features in Java 8. Next post will show the new Stream API and how it can greatly reduce some boilerplate code around lists and maps.