由于此处的许多答案都很好地解释了::
行为,因此我想澄清一下,如果将::
运算符用于实例变量,则运算符不需要具有与引用函数接口完全相同的签名。假设我们需要一个类型为TestObject的BinaryOperator。按照传统方式,其实现方式如下:
BinaryOperator<TestObject> binary = new BinaryOperator<TestObject>() {
@Override
public TestObject apply(TestObject t, TestObject u) {
return t;
}
};
如您在匿名实现中所看到的,它需要两个TestObject参数,并且还返回一个TestObject对象。为了通过使用::
运算符来满足此条件,我们可以从静态方法开始:
public class TestObject {
public static final TestObject testStatic(TestObject t, TestObject t2){
return t;
}
}
然后致电:
BinaryOperator<TestObject> binary = TestObject::testStatic;
好的,编译良好。如果我们需要实例方法呢?让我们用实例方法更新TestObject:
public class TestObject {
public final TestObject testInstance(TestObject t, TestObject t2){
return t;
}
public static final TestObject testStatic(TestObject t, TestObject t2){
return t;
}
}
现在我们可以访问实例如下:
TestObject testObject = new TestObject();
BinaryOperator<TestObject> binary = testObject::testInstance;
这段代码可以很好地编译,但是不能编译以下代码:
BinaryOperator<TestObject> binary = TestObject::testInstance;
月食告诉我 “无法从类型TestObject静态引用非静态方法testInstance(TestObject,TestObject)...”
足够公平的是它的一个实例方法,但是如果我们testInstance
如下重载:
public class TestObject {
public final TestObject testInstance(TestObject t){
return t;
}
public final TestObject testInstance(TestObject t, TestObject t2){
return t;
}
public static final TestObject testStatic(TestObject t, TestObject t2){
return t;
}
}
并致电:
BinaryOperator<TestObject> binary = TestObject::testInstance;
该代码将编译正常。因为它将testInstance
使用单参数而不是双参数来调用。好吧,我们的两个参数发生了什么?让我们打印输出并查看:
public class TestObject {
public TestObject() {
System.out.println(this.hashCode());
}
public final TestObject testInstance(TestObject t){
System.out.println("Test instance called. this.hashCode:"
+ this.hashCode());
System.out.println("Given parameter hashCode:" + t.hashCode());
return t;
}
public final TestObject testInstance(TestObject t, TestObject t2){
return t;
}
public static final TestObject testStatic(TestObject t, TestObject t2){
return t;
}
}
将输出:
1418481495
303563356
Test instance called. this.hashCode:1418481495
Given parameter hashCode:303563356
好的,JVM足够聪明,可以调用param1.testInstance(param2)。我们可以使用testInstance
其他资源但不能使用TestObject 吗,即:
public class TestUtil {
public final TestObject testInstance(TestObject t){
return t;
}
}
并致电:
BinaryOperator<TestObject> binary = TestUtil::testInstance;
它不会编译,编译器会告诉您:“类型TestUtil没有定义testInstance(TestObject,TestObject)”。因此,如果编译器不是同一类型,则它将查找静态引用。好吧,多态性呢?如果删除最终修饰符并添加SubTestObject类:
public class SubTestObject extends TestObject {
public final TestObject testInstance(TestObject t){
return t;
}
}
并致电:
BinaryOperator<TestObject> binary = SubTestObject::testInstance;
它也不会编译,编译器仍会寻找静态引用。但是下面的代码可以编译良好,因为它通过了-测试:
public class TestObject {
public SubTestObject testInstance(Object t){
return (SubTestObject) t;
}
}
BinaryOperator<TestObject> binary = TestObject::testInstance;
*我只是在学习,所以我通过尝试来弄清楚了,如果我错了,请随时纠正我