Java 方法引用-无效的方法引用-不能是来自静态上下文的引用

Java 方法引用-无效的方法引用-不能是来自静态上下文的引用,java,java-8,Java,Java 8,我有下面的代码 StringJoiner joiner = new StringJoiner(", "); joiner.add("Something"); Function<StringJoiner,Integer> lengthFunc = StringJoiner::length; Function<CharSequence,StringJoiner> addFunc = StringJoiner::add; 我知道这个方法不能静态使用,我应该有如下的东西: F

我有下面的代码

StringJoiner joiner = new StringJoiner(", ");
joiner.add("Something");
Function<StringJoiner,Integer> lengthFunc =  StringJoiner::length;
Function<CharSequence,StringJoiner> addFunc = StringJoiner::add;
我知道这个方法不能静态使用,我应该有如下的东西:

Function<CharSequence,StringJoiner> addFunc = joiner::add;
函数addFunc=joiner::add;
相反。但是我不明白为什么第三行是
StringJoiner::length对于java编译器来说是完全正确的。有人能解释一下为什么会这样吗?

因为
StringJoiner.length
接受零参数,所以方法引用总体上接受
StringJoiner
(任意实例)并返回一个
整数。换句话说,第一个指定的方法ref相当于:

Function<StringJoiner, Integer> lengthFunc = new Function<StringJoiner, Integer>() {

       @Override
        public Integer apply(StringJoiner stringJoiner) {
            return stringJoiner.length;
        }
}
BiFunction<StringJoiner, CharSequence, StringJoiner> addFunc = new BiFunction<StringJoiner, CharSequence, StringJoiner>() {

       @Override
        public StringJoiner apply(StringJoiner stringJoiner, CharSequence charSequence) {
            return stringJoiner.add(charSequence);
        }
}
在契约中,
StringJoiner.add(CharSequence)
接受一个参数,因此总体上,
函数
必须接受(1)StringJoiner的任意实例,(2)CharSequence
并返回一个
StringJoiner

您可以将引用指定给一个
双功能
,该功能执行以下操作:

BiFunction<StringJoiner, CharSequence, StringJoiner> addFunc = StringJoiner::add;
addFunc
是一个
函数,它接受
CharSequence
并返回
StringJoiner
StringJoiner
的实例方法与此接口不匹配,因为该函数没有应用
add
方法的输入
StringJoiner
实例

您需要一个
BiFunction
来匹配
StringJoiner::add的签名:

BiFunction<StringJoiner,CharSequence,StringJoiner> addFunc = StringJoiner::add;
BiFunction addFunc=StringJoiner::add;

什么是StringJoiner的仲裁实例?我看到它被视为将调用apply方法的对象类型,但我不确定它是如何处理的works@ArturSkrzydło我已经详细阐述了它们如何使用纯匿名类进行等效。所谓任意实例,我指的是在调用方法引用的上下文中使用的某个实例。这是一个很好的匿名函数实现示例。@ArturSkrzydło是的,您可能需要编写自己的函数接口或使用其他解决方法。你可能想检查一下。要补充一点,我个人会避免使用
TriFunction
(因为这会使代码更复杂),并使它更像一个复合函数,首先我将
整数
附加到
字符序列
,然后调用原始的
双函数。这一点解释得非常清楚。现在,如果您使用的是
joiner::add
,那么这将是一个有效的
函数
。。。
BiFunction<StringJoiner, CharSequence, StringJoiner> addFunc = new BiFunction<StringJoiner, CharSequence, StringJoiner>() {

       @Override
        public StringJoiner apply(StringJoiner stringJoiner, CharSequence charSequence) {
            return stringJoiner.add(charSequence);
        }
}
StringJoiner sj1 = ...  // an arbitrary StringJoiner
sj1 = addFunc.apply(sj1, "a"); // no need to re-assign, but just to show the return type
Function<StringJoiner,Integer> lengthFunc =  StringJoiner::length;
Function<CharSequence,StringJoiner> addFunc = StringJoiner::add
BiFunction<StringJoiner,CharSequence,StringJoiner> addFunc = StringJoiner::add;