Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
125 views
in Technique[技术] by (71.8m points)

java 8 - Method Reference - passing Function to method with Consumer argument

I'm learning about Method References from Java 8 and I have difficulties understanding why does this work?

class Holder {
    private String holded;

    public Holder(String holded) {
        this.holded = holded;
    }

    public String getHolded() {
        return holded;
    }
}

private void run() {
    Function<Holder, String> getHolded = Holder::getHolded;

    consume(Holder::getHolded); //This is correct...
    consume(getHolded);         //...but this is not
}

private void consume(Consumer<Holder> consumer) {
    consumer.accept(null);
}

As you can see in run method - Holder::getHolded returns unbound method reference which you can invoke by passing object of type Holder as an argument. Like this: getHolded.apply(holder)

But why it casts this unbound method reference to Consumer when it is invoked directly as an method argument, and it does not doing it when I'm passing Function explicitly?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Two things here, lambda expressions are poly expressions - they are inferred by the compiler using their context (like generics for example).

When you declare consume(Holder::getHolded);, compiler (under the so-called special void compatibility rule) will infer it to Consumer<Holder>.

And this might not look obvious, but think of a simplified example. It is generally more than ok do call a method and discard it's return type, right? For example:

List<Integer> list = new ArrayList<>();
list.add(1);

Even if list.add(1) returns a boolean, we don't care about it.

Thus your example that works can be simplified to:

consume(x -> {
        x.getHolded(); // ignore the result here
        return;
});

So these are both possible and valid declarations:

Consumer<Holder> consumer = Holder::getHolded;
Function<Holder, String> function = Holder::getHolded;

But in this case we are explicitly telling what type is Holder::getHolded,, it's not the compiler inferring, thus consume(getHolded); fails, a Consumer != Function after all.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...