Will java allow to use functional interfaces as me

2020-08-21 04:30发布

问题:

With the new java lambdas and the concept of functional interfaces, will it be possible to treat those functional interfaces as methods?

interface Func { void execute(int i); }

void call(Func f)
{
    f(1); //instead of f.execute(1);
}

I found a lot of information about the syntax of actual lambda expressions, but nothing about this.

回答1:

Your proposition

What you propose has been discussed on the lambda-dev mailing list before:

http://mail.openjdk.java.net/pipermail/lambda-dev/2012-February/004518.html

It was mainly rejected because of the various problems related to ambiguity that would arise for the parser / compiler. Or in Brian Goetz's terms:

I think, ultimately, this is just discomfort with the committment to functional interfaces instead of function types, and an attempt to backpedal towards a wishy-washy middle ground. I don't see this as offering a compelling enough benefit.

If you feel that such "wishy-washy" features would still add value to the Java language, you can try your luck again on one of the lambda mailing lists, maybe with compelling arguments :-)

An alternative

It is possible, but probably not as elegantly as in JavaScript as your example syntax suggests. According to the latest state-of-the-lambda by Brian Goetz, there will be method references as mentioned in chapters

8 Method references

[...]

9 Kinds of method references

[...] There are actually three different kinds of method references, each with slightly different syntax:

  • A static method
  • An instance method of a particular object
  • An instance method of an arbitrary object of a particular type

So in fact, your example would have to be rephrased along these lines:

interface Func { void execute(int i); }

void call(Block<Integer> block)
{
    block.run(1); //instead of f.execute(1);
}

You can now pass a reference to that execute method:

// Disclaimer: I didn't check this against a JDK8 compiler...
Func f = (i) -> { ; }; // Empty sample implementation
call(f::execute)

In other words, the "functional" style is to be implemented at the declaration-site of your call method, not at the use-site. But as with JavaScript, the use-site doesn't have to know about the name of the concrete method in Func. It can just accept a Block for methods returning void, or a Callable for methods returning a value.

Note that on JDK's Mercurial repository, things have changed already. You won't find run() any more, as mentioned in the state of the lambda. Other interesting types can be found in the java.util.functions package:

http://hg.openjdk.java.net/lambda/lambda/jdk/file/tip/src/share/classes/java/util/function



回答2:

If I am understanding your question correctly, you imply that given the functional interface Mapper declared as follows

interface Mapper<T,U> {
   public U map(T t);
}

If I implement this functional interface with a lambda expression as follows:

Mapper<Integer,String> itoa = (n) -> String.valueOf(n);

You would like to invoke the function interface as follows:

String val = itoa(10); //would yield "10"

And not as it is today:

String val = itoa.map(10);

I guess, the first invocation is syntactic sugar for the second one.

I have not read in any documentation or the mailing lists that they are planning to provide this feature in the coming release of the JDK. But I guess you could ask the question in the lambda mailing list. I don't see a reason why this could not be implemented.