Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Interface overriding extending functional interface method as default and having an abstract method works abruptly

@FunctionalInterface
interface StringConsumer extends Consumer<String> {
    @Override
    public default void accept(String s) {
        System.out.println(s.toUpperCase());
    }
    void print(String s);
}

public class Test {
    public static void main(String[] args) {
        StringConsumer stringConsumerImpl= s -> System.out.println(s.toLowerCase());
        List<String> list = Arrays.asList("Dr", "Mr", "Miss", "Mrs");
        list.forEach(stringConsumerImpl);
    }
}

Output:
DR
MR
MISS
MRS

So what is going on in this code is really weird for me. I am actually providing implementation of print method but when I run the code it actually uses implementation of default method.

I was expecting print implementation to work.
edit: when print method is deleted from StringConsumer it causes compilation error on main method

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Iterable.forEach is implemented like this:

default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

It calls the accept method of the Consumer you passed in, so that is why accept is called and not print. It is as simple as that.

You might have thought that forEach will call whatever lambda expression you passed in. This is not true. Lambda expressions are just a fancy way to create an implementation of an interface that has a single abstract method. The body of the lambda expression is the implementation of that single abstract method (print). It just saves you the trouble of writing a class like this and creating an instance of it:

class Foo implements StringConsumer {
    @Override
    public void print(String s) {
        System.out.println(s.toLowerCase());
    }
}

That interface is free to have other default methods and other methods can choose to call those default methods, instead of the abstract method the lambda implements. It’s just like every other variable of an interface type.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading