17

为什么这不起作用?我收到编译器错误“无法对非静态方法打印进行静态引用...”

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);
    }
}
4

6 回答 6

22

无论您使用方法引用、lambda 表达式还是普通方法调用,实例方法都需要适当的实例进行调用。该实例可以由函数调用提供,例如,如果forEach预期BiConsumer<Chapter3,String>它起作用。但是由于在您的情况下forEach期望 a Consumer<String>,因此范围内没有实例Chapter3。您可以通过更改Chapter3.printstatic方法或提供实例作为方法调用的目标来轻松解决此问题:

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>

于 2014-10-06T09:16:51.827 回答
21

以防万一您尝试从运行代码的同一对象应用实例方法

Arrays.asList("a", "b", "c").forEach(this::print);
于 2018-04-03T14:29:22.980 回答
10

forEach接受 a Consumer<? super T>(它的签名是default void forEach(Consumer<? super T> action)),它是一个函数式接口,带有一个accept(T t)只有一个参数的方法。

当您传递具有参数的方法的非静态方法引用时,您实际上有两个参数 -this对实例的引用Chapter3和 String 参数。forEach这与预期不符。

于 2014-10-02T20:13:31.977 回答
5

我想我现在明白了。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);
}
}
于 2014-10-02T20:13:14.943 回答
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选择“不能从静态上下文引用非静态方法”超出了我的理解。

于 2019-01-16T22:38:33.487 回答
-1

你可以制作你的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);
    }
}
于 2019-01-16T22:43:15.140 回答