簡體   English   中英

Java 8方法參考非靜態方法

[英]Java 8 Method Reference to non-static method

為什么這不起作用? 我得到編譯錯誤“無法對非靜態方法打印靜態引用...”

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在你的情況下期望一個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>調用該實例上的方法,可以構建。

forEach接受Consumer<? super T> Consumer<? super T> (它的簽名是default void forEach(Consumer<? super T> action) ),這是一個帶有一個參數accept(T t)的函數接口。

當你傳遞有一個參數的方法的非靜態方法的參考,你實際上有兩個參數-在this參照Chapter3實例和字符串參數。 這與forEach期望的不匹配。

我想我現在明白了。 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);
}
}

以防您是否嘗試從運行代碼的同一對象應用實例方法

Arrays.asList("a", "b", "c").forEach(this::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);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM