为什么这不起作用?我得到编译错误"无法对非静态方法打印静态引用..."
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);
}
}
答案 0 :(得分:14)
无论是使用方法引用,lambda表达式还是普通方法调用,实例方法都需要适当的实例来进行调用。该实例可以由函数调用提供,例如,如果forEach
预期BiConsumer<Chapter3,String>
有效。但由于forEach
在您的情况下需要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()
(Chapter3
的新实例的结果将被捕获用于其print
方法的方法引用和Consumer<String>
调用该方法的结果该实例可以构建。
答案 1 :(得分:8)
forEach
接受Consumer<? super T>
(其签名为default void forEach(Consumer<? super T> action)
),这是一个功能接口,其方法accept(T t)
只有一个参数。
当您传递具有参数的方法的非静态方法引用时,实际上有两个参数 - this
对Chapter3
实例的引用和String参数。这与forEach
期望的内容不符。
答案 2 :(得分:4)
我想我现在明白了。 Stream中的内容是String类型,因此我无法在String intance上调用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);
}
}
答案 3 :(得分:4)
如果您尝试从运行代码的同一对象应用实例方法
,以防万一Arrays.asList("a", "b", "c").forEach(this::print);
答案 4 :(得分:0)
如果您将函数的类型与生成函数的对象不匹配,则会看到非静态错误。例如,以下代码行将无法编译,因为该函数希望将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选择“无法从静态上下文中引用非静态方法”超出了我的范围。
答案 5 :(得分:0)
您可以使用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);
}
}