Java 8方法参考非静态方法

时间:2014-10-02 20:08:06

标签: java java-8 method-reference

为什么这不起作用?我得到编译错误"无法对非静态方法打印静态引用..."

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

6 个答案:

答案 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)只有一个参数。

当您传递具有参数的方法的非静态方法引用时,实际上有两个参数 - thisChapter3实例的引用和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);
    }
}