简体   繁体   English

方法参考投射如何工作?

[英]How does method reference casting work?

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

Both are instance methods with same signature. 两者都是具有相同签名的实例方法。 Why does one work and the other doesn't? 为什么一个工作而另一个不工作?

Signature of String::toUpperCase : String toUpperCase(); String::toUpperCase签名: String toUpperCase();

There are 3 constructs to reference a method: 有3个构造引用方法:

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

The line: 这条线:

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

use 3'rd construct - Class::instanceMethod . 使用3'rd构造 - Class::instanceMethod In this case first parameter becomes the target of the method . 在这种情况下, 第一个参数成为方法的目标 This construct is equivalent (translates) to following Lambda: 此构造与以下Lambda等效(翻译):

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

This Lambda expression works because Lambda gets String as parameter and returns String result - as required by Capitalizer interface . 此Lambda表达式起作用,因为Lambda String作为参数并返回String结果 - 根据Capitalizer接口的要求

The line: 这条线:

c = Main::toUpperCase; //Compile error

Translates to: 翻译为:

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

Which does not work with the Capitalizer interface. 哪个不适用于Capitalizer界面。 You could verify this by changing Capitalizer to: 您可以通过将Capitalizer更改为:

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

After this change Main::toUpperCase will compile. 在此更改后, Main::toUpperCase将进行编译。

You have a method which 你有一个方法

public String capitalize(String name);

Takes a String and returns a String . 获取String并返回String Such a method can have a number of patterns. 这种方法可以具有许多模式。

A constructor 构造函数

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

A function on String which takes no arguments String上的函数,不带参数

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

of a method which takes a String as the only argument 将String作为唯一参数的方法

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

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

In every case, the method referenced has to take the String. 在每种情况下,引用的方法都必须采用String。

If not you can do this instead. 如果不是,你可以这样做。

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

This tells the compiler to ignore the input. 这告诉编译器忽略输入。

You should change: 你应该改变:

public String toUpperCase()

to

public static String toUpperCase(String text)

You should read the java tutorial on method references . 您应该阅读有关方法引用的java教程。 The different kind of method references and there is a similar example with String::compareToIgnoreCase (Reference to an Instance Method of an Arbitrary Object of a Particular Type). 不同类型的方法引用和String::compareToIgnoreCase (引用特定类型的任意对象的实例方法)有类似的例子。

The equivalent lambda expression for the method reference String::compareToIgnoreCase would have the formal parameter list (String a, String b), where a and b are arbitrary names used to better describe this example. 方法引用String :: compareToIgnoreCase的等效lambda表达式将具有形式参数列表(String a,String b),其中a和b是用于更好地描述此示例的任意名称。 The method reference would invoke the method a.compareToIgnoreCase(b). 方法引用将调用方法a.compareToIgnoreCase(b)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM