Java 8 lambda expression with an abstract class having only one method

navy1978 :

I'm learning lambda expressions in Java 8. Can somebody explain to me how to use lambda expression with an abstract class having only one method (if it's possible)?

For example, this is the abstract class:

public abstract class ClassA {

    public abstract void action();

}

And I have another class that take's in its constructor an instance of ClassA:

public ClassB {
   public ClassB(String text, ClassA a){
      //Do stuff
    }
}

So I was wondering how to write something like this:

ClassB b = new ClassB("Example", new ClassA(() -> System.out.println("Hello")));

Obviously that statement doesn't work, but is there a way to use a lambda expression here or not? If there is, what am I doing wrong?

Alex Mamo :

No, you cannot achieve this because ClassA must be a functional interface. A functional interface is an interface that contains exactly one abstract method. It may contain zero or more default methods and/or static methods in addition to the abstract method. Because a functional interface contains exactly one abstract method, you can omit the name of that method when you implement it using a lambda expression. For example, consider the following interface:

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

The purpose of this interface is to provide a method that operates on an object of class T and return a boolean. You could have a method that takes an instance of class that implements this interface defined like this:

public void printImportantData(ArrayList<Data> dataList, Predicate<Data> p) {
    for (Data d : dataList) {
        if (p.test(d)) {
            System.out.println(d);
        }
    }
}

where Data class could be as simple as:

public class Data {
    public int value;
}

Now, you can call the above method as follows:

 printImportantData(al, (Data d) -> { return d.value > 1; }); 

Notice the method does not have a name here. This is possible because the interface has only one abstract method so the compiler can figure out the name. This can be shortened to:

printImportantData(al, (Data d) -> d.value > 1);

Notice that here are no curly brackets and no return keyword. This is possible because the method returns a boolean and the expression d.value > 1 also returns a boolean. The compiler is therefore able to figure out that the value of this expression is to be returned from the method. This can be shortened even more to:

printImportantData(al, d -> d.value > 1);

Notice that there is no type declaration of d! The compiler can figure out all information it needs because the interface has only one abstract method and that method has only one parameter. So you don't need to write all those things in your code.
Compare the above approach to the old Java 7 style using an inner class that does effectively the same thing:

printImportantData(al, new Predicate<Data>() {
    public boolean test(Data d) {
        return d.value > 1;
    }
});

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=435458&siteId=1