Kir*_*rov 5 java java-8 method-reference
我试图理解方法引用如何在java中工作.乍一看,它非常简单.但是当谈到这样的事情时:
Foo类中有一个方法:
public class Foo {
public Foo merge(Foo another) {
//some logic
}
}
Run Code Online (Sandbox Code Playgroud)
在另一个类Bar中有一个这样的方法:
public class Bar {
public void function(BiFunction<Foo, Foo, Foo> biFunction) {
//some logic
}
}
Run Code Online (Sandbox Code Playgroud)
并使用方法参考:
new Bar().function(Foo::merge);
Run Code Online (Sandbox Code Playgroud)
它符合并且有效,但我不明白它是如何匹配的:
Foo merge(Foo another)
Run Code Online (Sandbox Code Playgroud)
到BiFunction方法:
R apply(T t, U u);
Run Code Online (Sandbox Code Playgroud)
???
this实例方法有一个隐式参数。这是JVM 规范的 \xc2\xa73.7定义的:
\n\n\n通过首先将对当前实例 this 的引用推送到操作数堆栈来设置调用。然后压入方法调用的参数 int 值 12 和 13。创建 addTwo 方法的框架时,传递给该方法的参数将成为新框架局部变量的初始值。也就是说,调用者推送到操作数堆栈上的此参数和两个参数的引用将成为被调用方法的局部变量 0、1 和 2 的初始值。
\n
要理解为什么方法调用是这样完成的,我们需要了解 JVM 如何在内存中存储代码。对象的代码和数据是分开的。事实上,一个类的所有方法(静态和非静态)都存储在同一个地方,即方法区(JVM规范的\xc2\xa72.5.4)。这允许仅存储每个方法一次,而不是一遍又一遍地为类的每个实例重新存储它们。当像这样的方法
\n\nsomeObject.doSomethingWith(someOtherObject);\nRun Code Online (Sandbox Code Playgroud)\n\n被调用,它实际上被编译成看起来更像的东西
\n\ndoSomething(someObject, someOtherObject);\nRun Code Online (Sandbox Code Playgroud)\n\n大多数 Java 程序员都会同意它someObject.doSomethingWith(someOtherObject)具有“较低的认知复杂性”:我们用someObject涉及someOtherObject. 这个行动的中心是someObject,其中someOtherObject只是达到目的的手段。
使用doSomethingWith(someObject, someOtherObject),您无需传输someObject作为操作中心的语义。
所以本质上,我们编写了第一个版本,但计算机更喜欢第二个版本。
\n\n正如 @FedericoPeraltaSchaffner 所指出的,从 Java 8 开始,您甚至可以显式编写隐式参数。确切的定义在JLS, \xc2\xa78.4.1this中给出:
\n\n\n接收者参数是实例方法或内部类构造函数的可选语法设备。对于实例方法,接收者参数表示调用该方法的对象。对于内部类的构造函数,接收者参数表示新构造对象的直接封闭实例。无论哪种方式,接收者参数的存在只是为了允许在源代码中表示所表示的对象的类型,以便可以对类型进行注释。接收者参数不是形式参数;更准确地说,它不是任何类型变量的声明 (\xc2\xa74.12.3),它永远不会绑定到在方法调用表达式或限定类实例创建表达式中作为参数传递的任何值,并且它没有任何效果无论在运行时。
\n
接收者参数必须是类的类型并且必须命名this。
这意味着
\n\npublic String doSomethingWith(SomeOtherClass other) { ... }\nRun Code Online (Sandbox Code Playgroud)\n\n和
\n\npublic String doSomethingWith(SomeClass this, SomeOtherClass other) { ... }\nRun Code Online (Sandbox Code Playgroud)\n\n将具有相同的语义,但后者允许例如注释。
\n| 归档时间: |
|
| 查看次数: |
192 次 |
| 最近记录: |