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
241 views
in Technique[技术] by (71.8m points)

java - Function and Predicate parameter ambiguous?

Using Java 8, I get a compiler error for the following code:

public class Ambiguous {
    public static void call() {
        SomeDataClass data = new SomeDataClass();
        callee(data, SomeDataClass::getString);
        // compiler errors:
        // 1. at callee method name:
        // The method callee(SomeDataClass, Function<SomeDataClass,String>) is ambiguous for the type Ambiguous
        // 2. at lambda:
        // Type mismatch: cannot convert from boolean to String
        callee(data, d -> d.getRandom() > 0.5);
    }

    public static void callee(SomeDataClass data, Function<SomeDataClass, String> extractString) {
        System.out.println(extractString.apply(data));
    }

    public static void callee(SomeDataClass data, Predicate<SomeDataClass> check) {
        System.out.println(check.test(data));
    }
}

// token data class
final class SomeDataClass {
    public String getString() {
        return "string";
    }

    public final double getRandom() {
        return Math.random();
    }
}

So essentially the compiler says "I know you return boolean but you shouldn't, and if you don't I'm not sure what method to use" instead of "oh you're returning boolean, you must mean the Predicate version of the method"? How does this confusion get created?

I'd understand if Predicate<T> extends Function<T, Boolean> (so they have a common Type) but that's not the case.

I do know how to fix it; it's fine if I do

callee(data, (Predicate<SomeDataClass>) d -> d.getRandom() > 0.5);

but I'm curious what causes it.

See Question&Answers more detail:os

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

1 Answer

0 votes
by (71.8m points)

This can be simplified a bit for clarity:

public static void m(Predicate<Integer> predicate){

}

public static void m(Function<Integer, String> function){

}

And calling it with:

m(i -> "test")

What do you think will happen? Same thing as in your question.

Compiler here has to know the method in order to find the target type, but it needs to know the target type in order to resolve the method (it's like a deadlock).

When you add a cast to Predicate..., you are creating an explicit target type, return type of which is taken into consideration for method overloading as far as I understand.


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

2.1m questions

2.1m answers

60 comments

57.0k users

...