How does method reference casting work?

 ̄綄美尐妖づ 提交于 2019-12-19 08:59:40

问题


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


回答1:


There are 3 constructs to reference a method:

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

The line:

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

use 3'rd construct - Class::instanceMethod. In this case first parameter becomes the target of the method. This construct is equivalent (translates) to following 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.

The line:

c = Main::toUpperCase; //Compile error

Translates to:

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

Which does not work with the Capitalizer interface. You could verify this by changing Capitalizer to:

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

After this change Main::toUpperCase will compile.




回答2:


You have a method which

public String capitalize(String name);

Takes a String and returns a 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

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

of a method which takes a String as the only argument

// 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.

If not you can do this instead.

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

This tells the compiler to ignore the input.




回答3:


You should change:

public String toUpperCase()

to

public static String toUpperCase(String text)

You should read the java tutorial on method references. 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).

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. The method reference would invoke the method a.compareToIgnoreCase(b).



来源:https://stackoverflow.com/questions/30025555/how-does-method-reference-casting-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!