由于许多答案在这里解释well :: behavior,另外我想澄清一下:: 运算符如果用于实例variables,不需要与引用的Functional Interface具有完全相同的签名 。 让我们假设我们需要一个具有TestObjecttypes的BinaryOperator 。 传统的方式是这样实现的:
BinaryOperator binary = new BinaryOperator() { @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 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 binary = testObject::testInstance;
这段代码编译得很好,但是下面的代码不是:
BinaryOperator binary = TestObject::testInstance;
我的eclipse告诉我: “不能从typesTestObject的非静态方法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 binary = TestObject::testInstance;
该代码将只是编译好。 因为它将使用单个参数而不是双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 binary = TestUtil::testInstance;
它只是不编译,编译器会告诉: “typesTestUtil没有定义testInstance(TestObject,TestObject)” 。 所以编译器会寻找一个静态引用,如果它不是相同的types。 好的多态性呢? 如果我们删除最终修饰符并添加我们的SubTestObject类:
public class SubTestObject extends TestObject { public final TestObject testInstance(TestObject t){ return t; } }
并致电:
BinaryOperator binary = SubTestObject::testInstance;
它不会编译,编译器仍然会查找静态引用。 但是,下面的代码将通过testing:
public class TestObject { public SubTestObject testInstance(Object t){ return (SubTestObject) t; } } BinaryOperator binary = TestObject::testInstance;
*我只是在学习,所以我试着去了解,如果我错了,请随时纠正我