为什么这不起作用?我收到编译器错误“无法对非静态方法打印进行静态引用...”
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);
}
}
为什么这不起作用?我收到编译器错误“无法对非静态方法打印进行静态引用...”
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);
}
}
无论您使用方法引用、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);
}
}
在这里,将捕获的结果new Chapter3(),一个新的实例,用于方法引用其方法,并且可以构造对该实例的方法调用。Chapter3printConsumer<String>
以防万一您尝试从运行代码的同一对象应用实例方法
Arrays.asList("a", "b", "c").forEach(this::print);
forEach接受 a Consumer<? super T>(它的签名是default void forEach(Consumer<? super T> action)),它是一个函数式接口,带有一个accept(T t)只有一个参数的方法。
当您传递具有参数的方法的非静态方法引用时,您实际上有两个参数 -this对实例的引用Chapter3和 String 参数。forEach这与预期不符。
我想我现在明白了。Stream 中的内容是 String 类型,因此我不能在 String 实例上调用 print...
例如这有效
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);
}
}
如果您不匹配函数的类型和从中生成函数的对象,您将看到非静态错误。例如,这行代码不会编译,因为函数需要 Foo 作为它所作用的类型,但该函数是针对 Foobar 的:
Function<Foo, Bar> func = Foobar::getBar;
它不仅处理它在 for 循环或任何其他参数中的时间,也不必处理“范围内的内容”。这是 java 在使用新函数对象时错误标记的类型不匹配错误。将此与构造其他泛型时发生的情况进行比较:
List<Foo> list = new ArrayList<Bar>();
该行代码将无法编译并出现错误“不兼容的类型”。更好的是,尽管也以几乎完全相同的方式处理功能对象,但此代码也会因不兼容的类型而失败:
public void test() {
Function<Foo, Double> test2 = Foo::getDouble;
//fails with Incompatible types
test3(test2);
}
public void test3(Function<Foobar, Double> function) {
//who cares
}
我最好的建议是,当您开始遇到此错误时,将函数声明拉到新行,您应该能够看到实际问题是什么。为什么java选择“不能从静态上下文引用非静态方法”超出了我的理解。
你可以制作你的print函数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);
}
}