4
public class Main {
    interface Capitalizer {
        public String capitalize(String name);
    }

    public String toUpperCase() {
        return "ALLCAPS";
    }

    public static void main(String[] args) {
        Capitalizer c = String::toUpperCase; //This works
        c = Main::toUpperCase; //Compile error
    }
}

两者都是具有相同签名的实例方法。为什么一个有效而另一个无效?

签名String::toUpperCaseString toUpperCase();

4

3 回答 3

6

有 3 个构造来引用方法:

  1. object::instanceMethod
  2. Class::staticMethod
  3. Class::instanceMethod

该行:

Capitalizer c = String::toUpperCase; //This works

使用第三个构造 - Class::instanceMethod。在这种情况下,第一个参数成为方法的目标。此构造等效于(翻译)以下 Lambda:

Capitalizer = (String x) -> x.toUpperCase();

这个 Lambda 表达式之所以有效,是因为 Lambda作为参数获取String并返回String结果 - 正如Capitalizerinterface所要求的那样。

该行:

c = Main::toUpperCase; //Compile error

转换为:

(Main m) ->  m.toUpperCase();

哪个不适用于Capitalizer界面。您可以通过更改Capitalizer为:

interface Capitalizer {
    public String capitalize(Main name);
}

此更改Main::toUpperCase后将编译。

于 2015-05-04T13:15:28.453 回答
4

你有一个方法

public String capitalize(String name);

接受 aString并返回 a String。这种方法可以有多种模式。

一个构造函数

c = String::new; // calls new String(String)
// or
c = s -> new String(s);

String不带参数的函数

c = String::toLowerCase; // instance method String::toLowerCase()
// or
c = s -> s.toLowerCase();

将 String 作为唯一参数的方法

// method which takes a String, but not a Main
public static String toUpperCase(String str) { 

c = Main::toUpperCase;
// or
c = s -> toUpperCase(s);

在任何情况下,引用的方法都必须采用字符串。

如果没有,你可以这样做。

c = s -> capitalize(); // assuming Main.capitalize() is static

这告诉编译器忽略输入。

于 2015-05-04T08:23:34.057 回答
0

你应该改变:

public String toUpperCase()

public static String toUpperCase(String text)

您应该阅读有关方法引用的 java 教程。不同类型的方法引用并且有一个类似的示例String::compareToIgnoreCase(引用特定类型的任意对象的实例方法)。

方法引用 String::compareToIgnoreCase 的等效 lambda 表达式将具有形式参数列表 (String a, String b),其中 a 和 b 是用于更好地描述此示例的任意名称。方法引用将调用方法 a.compareToIgnoreCase(b)。

于 2015-05-04T08:22:14.203 回答