Java 8 非静态方法的方法参考
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26168806/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java 8 Method Reference to non-static method
提问by andres.santana
Why this doesn't work? I get compiler error "Cannot make static reference to the non static method print..."
为什么这不起作用?我收到编译器错误“无法对非静态方法打印进行静态引用...”
public class Chapter3 {
public void print(String s) {
System.out.println(s);
}
public static void main(String[] args) {
Arrays.asList("a", "b", "c").forEach(Chapter3::print);
}
}
回答by Holger
Regardless of whether you use method references, lambda expressions or ordinary method calls, an instance method requires an appropriate instance for the invocation. The instance may be supplied by the function invocation, e.g. if forEach
expected a BiConsumer<Chapter3,String>
it worked. But since forEach
expects a Consumer<String>
in your case, there is no instance of Chapter3
in scope. You can fix this easily by either, changing Chapter3.print
to a static
method or by providing an instance as target for the method invocation:
无论您使用方法引用、lambda 表达式还是普通方法调用,实例方法都需要一个适当的实例来进行调用。实例可以由函数调用提供,例如,如果forEach
预期BiConsumer<Chapter3,String>
它工作。但是由于在您的情况下forEach
期望 a Consumer<String>
,因此Chapter3
在范围内没有实例。您可以通过更改Chapter3.print
为static
方法或提供实例作为方法调用的目标来轻松解决此问题:
public class Chapter3 {
public void print(String s) {
System.out.println(s);
}
public static void main(String[] args) {
Arrays.asList("a", "b", "c").forEach(new Chapter3()::print);
}
}
Here, the result of new Chapter3()
, a new instance of Chapter3
, will be captured for the method reference to its print
method and a Consumer<String>
invoking the method on that instance can be constructed.
在这里, 的结果new Chapter3()
, 的一个新实例Chapter3
,将被捕获用于对其print
方法的方法引用,并且Consumer<String>
可以构造在该实例上调用该方法的方法。
回答by Eran
forEach
accepts a Consumer<? super T>
(its signature is default void forEach(Consumer<? super T> action)
), which is a functional interface with a method accept(T t)
that has a single argument.
forEach
接受一个Consumer<? super T>
(它的签名是default void forEach(Consumer<? super T> action)
),它是一个函数式接口,带有一个accept(T t)
只有一个参数的方法。
When you pass a non-static method reference of a method that has an argument, you actually have two arguments - the this
reference to the Chapter3
instance and the String argument. This doesn't match what forEach
expects.
当您传递具有参数的方法的非静态方法引用时,您实际上有两个参数 -this
对Chapter3
实例的引用和 String 参数。这与forEach
预期不符。
回答by Sergey Shcherbakov
Just in case if you are trying to apply an instance method from the same object where your code runs
以防万一,如果您尝试从运行代码的同一对象应用实例方法
Arrays.asList("a", "b", "c").forEach(this::print);
回答by andres.santana
I think I got it now. What's in the Stream is of type String therefore I can't call print on a String intance...
我想我现在明白了。Stream 中的内容是 String 类型,因此我无法在 String 实例上调用 print ...
For example this works
例如这有效
public class Chapter3 {
final String value;
public Chapter3(String value) {
this.value = value;
}
public void print() {
System.out.println(value);
}
public static void main(String[] args) {
Arrays.asList(new Chapter3("a"), new Chapter3("b")).forEach(Chapter3::print);
}
}
回答by Taugenichts
If you mismatch types of the function and the objects you are generating the function from, you will see the non static error. For example, this line of code will not compile because the function expects a Foo as the type it is acting on, but the function is for a Foobar:
如果函数的类型与生成函数的对象不匹配,您将看到非静态错误。例如,这行代码将无法编译,因为该函数期望 Foo 作为它所作用的类型,但该函数用于 Foobar:
Function<Foo, Bar> func = Foobar::getBar;
It doesn't just deal with when its in a for loop or any other argument nor does it have to deal with "what is in scope". It's a type mismatch error that java mislabeled when using the new function objects. Compare this to what happens when you construct other generics:
它不仅处理何时处于 for 循环或任何其他参数中,也不必处理“范围内的内容”。这是java在使用新函数对象时错误标记的类型不匹配错误。将此与构建其他泛型时发生的情况进行比较:
List<Foo> list = new ArrayList<Bar>();
That line of code will fail to compile with the error "Incompatible Types". Even better is that this code will also fail with incompatible types instead despite also dealing with functional objects in nearly the exact same way:
该行代码将无法编译,并显示错误“不兼容的类型”。更好的是,尽管也以几乎完全相同的方式处理功能对象,但此代码也会因不兼容的类型而失败:
public void test() {
Function<Foo, Double> test2 = Foo::getDouble;
//fails with Incompatible types
test3(test2);
}
public void test3(Function<Foobar, Double> function) {
//who cares
}
My best suggestion is when you start having this error, pull out the function declaration to a new line and you should be able to see what the actual issue is. Why java chose "non-static method cannot be referenced from a static context" is beyond me.
我最好的建议是,当您开始出现此错误时,将函数声明拉出到新行,您应该能够看到实际问题所在。为什么 java 选择“不能从静态上下文中引用非静态方法”超出了我的理解。
回答by Willi Mentzel
You could make your print
function static
, this way you don't need an instance to call it on:
你可以让你的print
function static
,这样你就不需要一个实例来调用它:
public class Chapter3 {
public static void print(String s) {
System.out.println(s);
}
public static void main(String[] args) {
Arrays.asList("a", "b", "c").forEach(Chapter3::print);
}
}