编写Java方法引用的简明方法?

时间:2021-06-13 22:04:24

Given some Java 8 method functions:

给定一些Java 8方法函数:

class Foo { Bar getBar() {} }
class Bar { Baz getBaz() {} }

A composition of the two accessors looks like:

这两个访问器的组成如下:

Function<Foo, Bar> getBarFromFoo = Foo::getBar;
Function<Bar, Baz> getBazFromBar = Bar::getBaz;
Function<Foo, Baz> getBazFromFoo = getBarFromFoo.andThen(getBazFromBar);

Is there a more concise way? This seems to work

有没有更简洁的方法?这似乎工作

((Function<Foo, Bar>) Foo::getBar).andThen(Bar::getBaz)

But it's rather ugly. The outer parens make sense for precedence reasons, but why is the cast necessary?

但它很丑。由于优先级的原因,外部参数是有意义的,但是为什么强制转换是必要的呢?

(Foo::getBar::getBaz would be nice, but alas...)

(Foo::getBar::getBaz很好,但是唉…)

4 个解决方案

#1


10  

Let's define a functional interface:

让我们定义一个功能接口:

@FunctionalInterface
interface MyFunctionalInterface {
    Bar getBar(Foo f);
}

We can simplify the method reference Foo::getBar a bit,

我们可以简化方法引用Foo::getBar一点,

(Foo foo) -> foo.getBar();

which means "take a Foo and return a Bar". For that description, a lot of methods are suitable (for instance, our interface with the getBar and a Funtion<Foo, Bar> with its apply):

意思是“拿一个Foo然后返回一个Bar”。对于这种描述,有许多方法是合适的(例如,我们与getBar的接口和函数 及其应用): ,>

MyFunctionalInterface f1 = (Foo foo) -> foo.getBar();
Function<Foo, Bar> f2 = (Foo foo) -> foo.getBar();

That is the answer to the question why the cast is necessary.

这就是为什么演员是必须的问题的答案。


To answer the question whether there is a more concise way affirmatively, we have to set a context. The context unambiguously gives us a Function to continue working with:

要确定是否有更简洁的方式,我们必须建立一个背景。上下文明确地给了我们一个继续工作的函数:

class Functions {
    public static <I, O> Function<I, O> of(Function<I, O> function) {
        return function;
    }
}

Functions.of(Foo::getBar).andThen(Bar::getBaz);

#2


3  

There is no dedicated way of composing functions in Java other than andThen().

除了andThen()之外,Java中没有专门的函数组合方式。

You need to perform the cast because Foo::getBar is ambiguous. **It could match every interface having similar method signature.

您需要执行cast,因为Foo::getBar是不明确的。**它可以匹配每个具有相似方法签名的接口。

Unfortunately, ((Function<Foo, Bar>) Foo::getBar).andThen(Bar::getBaz) is the best you can do.

然后(Bar::getBaz)是你能做的最好的事情。

#3


1  

Maybe just use a lambda expression?

也许只用一个lambda表达式?

x -> x.getBar().getBaz()

There is no other way to compose functions other than what you already suggested because of type ambiguity. This is not even much longer than Foo::getBar::getBaz

由于类型歧义,除了您已经建议的方法之外,没有其他方法组合函数。这甚至比Foo::getBar: getBaz长不了多少

#4


0  

That's the best you are going to get. If you think that this would work:

这是你能得到的最好的结果。如果你认为这行得通:

Foo::getBar::getBaz

it will not. That's because Foo::getBar is a poly expression - it depends on the context used - it could be a Function, but could also be a Predicate for example; so it could potentially apply to many things, so the cast is just necessary there.

它不会。这是因为Foo: getBar是一个poly表达式——它取决于所使用的上下文——它可以是一个函数,也可以是一个谓词,例如;所以它可能适用于很多东西,所以石膏只是必要的。

You could hide that behind a method that would do the chaining and andThen, but the problem is still there.

你可以把它隐藏在一个方法后面,然后进行链接,但是问题仍然存在。

EDIT

编辑

See an example here:

看一个例子:

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

}

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

}

and the expression cool(i -> "Test"); will fail to compile

和表示cool(i ->“Test”);将无法编译

#1


10  

Let's define a functional interface:

让我们定义一个功能接口:

@FunctionalInterface
interface MyFunctionalInterface {
    Bar getBar(Foo f);
}

We can simplify the method reference Foo::getBar a bit,

我们可以简化方法引用Foo::getBar一点,

(Foo foo) -> foo.getBar();

which means "take a Foo and return a Bar". For that description, a lot of methods are suitable (for instance, our interface with the getBar and a Funtion<Foo, Bar> with its apply):

意思是“拿一个Foo然后返回一个Bar”。对于这种描述,有许多方法是合适的(例如,我们与getBar的接口和函数 及其应用): ,>

MyFunctionalInterface f1 = (Foo foo) -> foo.getBar();
Function<Foo, Bar> f2 = (Foo foo) -> foo.getBar();

That is the answer to the question why the cast is necessary.

这就是为什么演员是必须的问题的答案。


To answer the question whether there is a more concise way affirmatively, we have to set a context. The context unambiguously gives us a Function to continue working with:

要确定是否有更简洁的方式,我们必须建立一个背景。上下文明确地给了我们一个继续工作的函数:

class Functions {
    public static <I, O> Function<I, O> of(Function<I, O> function) {
        return function;
    }
}

Functions.of(Foo::getBar).andThen(Bar::getBaz);

#2


3  

There is no dedicated way of composing functions in Java other than andThen().

除了andThen()之外,Java中没有专门的函数组合方式。

You need to perform the cast because Foo::getBar is ambiguous. **It could match every interface having similar method signature.

您需要执行cast,因为Foo::getBar是不明确的。**它可以匹配每个具有相似方法签名的接口。

Unfortunately, ((Function<Foo, Bar>) Foo::getBar).andThen(Bar::getBaz) is the best you can do.

然后(Bar::getBaz)是你能做的最好的事情。

#3


1  

Maybe just use a lambda expression?

也许只用一个lambda表达式?

x -> x.getBar().getBaz()

There is no other way to compose functions other than what you already suggested because of type ambiguity. This is not even much longer than Foo::getBar::getBaz

由于类型歧义,除了您已经建议的方法之外,没有其他方法组合函数。这甚至比Foo::getBar: getBaz长不了多少

#4


0  

That's the best you are going to get. If you think that this would work:

这是你能得到的最好的结果。如果你认为这行得通:

Foo::getBar::getBaz

it will not. That's because Foo::getBar is a poly expression - it depends on the context used - it could be a Function, but could also be a Predicate for example; so it could potentially apply to many things, so the cast is just necessary there.

它不会。这是因为Foo: getBar是一个poly表达式——它取决于所使用的上下文——它可以是一个函数,也可以是一个谓词,例如;所以它可能适用于很多东西,所以石膏只是必要的。

You could hide that behind a method that would do the chaining and andThen, but the problem is still there.

你可以把它隐藏在一个方法后面,然后进行链接,但是问题仍然存在。

EDIT

编辑

See an example here:

看一个例子:

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

}

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

}

and the expression cool(i -> "Test"); will fail to compile

和表示cool(i ->“Test”);将无法编译