尝试理解 Java 8 中的方法引用(将类方法分配给函数式接口)

huangapple go评论79阅读模式
英文:

Trying to understand method reference in Java 8 (assigning class method to functional interface)

问题

我正试图更好地理解方法引用是如何工作的。在这个例子中,我按照代码的逻辑进行,但我不太理解这样做的价值。基本上,在步骤2中的方法引用赋值之后,someMethod() 被用作 MyInterfacedisplay() 抽象方法的实现。但为什么?我们通过这样做获得了什么?在架构上什么时候会有意义?似乎我们将与类无关的接口与此赋值关联起来。

@FunctionalInterface
interface MyInterface {
    void display();
}

class DerivClass {
    public void someMethod() {  
        System.out.println("Derived class method");  
    }
}

public class RefTest {

    public static void main(String[] args) {
        DerivClass dc = new DerivClass(); // 步骤1:类实例化
        MyInterface myInterf = dc::someMethod; // 步骤2:将方法引用赋值给接口
        myInterf.display(); // 步骤3:执行 someMethod(),输出 "Derived class method"
    }
}
英文:

I am trying to better understand how method references work. In this example, I follow the logic of the code, but I don't understand the value of doing this. Basically, someMethod() is used as the implementation of the display() abstract method of MyInterface after the method reference assignment in STEP 2. But why? What are we gaining by doing this? When does this make sense architecturally? Seems that we take the Interface that has nothing to do with the class and associate them with this assignment.

@FunctionalInterface
interface MyInterface {
       void display();
}

class DerivClass {
    public void someMethod(){  
            System.out.println("Derived class method");  
    }
}

public class RefTest {

	public static void main(String[] args) {
		DerivClass dc = new DerivClass(); // STEP1: class instance
		MyInterface myInterf = dc::someMethod; // STEP 2: assign method ref to interface	
		myInterf.display(); // STEP 3: executes someMethod(), prints "Derived class method"
	}
}


</details>


# 答案1
**得分**: 9

方法引用是理解的好起点 *方法引用* 是 [Oracle 文档](https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html)。文档中提到:

> 您可以使用 lambda 表达式创建匿名方法。但有时,lambda 表达式只是调用现有方法而已。在这种情况下,通过名称引用现有方法通常更清晰。方法引用使您可以实现这一点;它们是紧凑且易于阅读的 lambda 表达式,适用于已经具有名称的方法。

可以这样理解:
> "*方法定义(特定的主体、签名和返回类型)已经存在;如果我可以重用现有代码,为什么要创建新的 lambda 表达式?让我们引用已经定义的方法并重用它。*"

---
有四种方法引用:
---

1. `SomeType::staticMethodName` - 引用静态方法(仅引用“SomeType”类的静态方法);

2. `someTypeInstance::instanceMethodName` - 引用特定对象的实例方法(在这里,您需要一个*实际*对象,从中获取方法引用);

3. `SomeType::instanceMethod` - 引用特定类型的任意对象的实例方法(在这种情况下,您不需要显式创建对象);

4. `SomeType::new` - 引用构造函数(仅引用构造函数)。

---

**(2) 特定对象方法引用和 (3) 任意对象方法引用之间的区别:**

在前两个示例中,方法引用等效于*提供*方法参数的 lambda 表达式。例如:
```java
System.out::println == x -> System.out.println(x);
Math::pow == (x, y) -> Math.pow(x, y)

在第三种情况下,第一个参数成为方法的目标,如下所示:

String::compareToIgnoreCase == (x, y) -> x.compareToIgnoreCase(y)
英文:

Good place you to start understanding the method reference is the Oracle Documentation, that says:

>You use lambda expressions to create anonymous methods. Sometimes, however, a lambda expression does nothing but call an existing method. In those cases, it's often clearer to refer to the existing method by name. Method references enable you to do this; they are compact, easy-to-read lambda expressions for methods that already have a name.

Think of it this way:
>"Method definition (particular body, signature and a return type) exists; why shall I create a new lambda expression if I can reuse existing code? let's refer to the already defined method and reuse it."


Four kinds of method references:

  1. SomeType::staticMethodName - reference to the static method (you just refer to the static method of "SomeType" class);

  2. someTypeInstance::instanceMethodName - reference to the instance method of a particular object (here, you need an actual object, from which you obtain the method reference);

  3. SomeType::instanceMethod - reference to the instance method of an arbitrary object of a particular type (you do not need to explicitly create an object in this case);

  4. SomeType::new - reference to the constructor (you simply refer to the constructor).


Difference between (2) the particular object's method reference and (3) arbitrary object's method reference:

In the first two examples, the method reference is equivalent to a lambda expression that supplies the parameters of the method. For example:

System.out::println == x -&gt; System.out.println(x);
Math::pow == (x, y) -&gt; Math.pow(x, y)

In the third case, the first parameter becomes the target of the method, as in:

String::compareToIgnoreCase == (x, y) -&gt; x.compareToIgnoreCase(y)

huangapple
  • 本文由 发表于 2020年10月14日 00:55:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/64339742.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定