由于这里的许多答案都很好地解释了:: 的行为,另外我想澄清:: 如果将操作员用于实例变量,则它不需要与引用的功能接口具有完全相同的签名。假设我们需要一个类型为 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;
我的eclipse告诉我“无法从类型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)。我们可以使用来自另一个资源而不是 TestObject 的testInstance,即:
public class TestUtil {
public final TestObject testInstance(TestObject t){
return t;
}
}
然后调用:
BinaryOperator<TestObject> binary = TestUtil::testInstance;
它不会编译并且编译器会告诉:“TestUtil 类型没有定义 testInstance(TestObject, TestObject)”。因此,如果它不是同一类型,编译器将查找静态引用。好的,多态性呢?如果我们移除 final 修饰符并添加我们的 SubTestObject 类:
public class SubTestObject extends TestObject {
public final TestObject testInstance(TestObject t){
return t;
}
}
然后调用:
BinaryOperator<TestObject> binary = SubTestObject::testInstance;
它也不会编译,编译器仍然会寻找静态引用。但是下面的代码可以正常编译,因为它通过了 is-a 测试:
public class TestObject {
public SubTestObject testInstance(Object t){
return (SubTestObject) t;
}
}
BinaryOperator<TestObject> binary = TestObject::testInstance;
*我只是在学习,所以我试着看看,如果我错了,请随时纠正我