Da hier viele Antworten das ::Verhalten gut erklärten , möchte ich zusätzlich klarstellen, dass der :: Operator nicht genau dieselbe Signatur wie die verweisende Funktionsschnittstelle haben muss, wenn er beispielsweise für Variablen verwendet wird . Nehmen wir an, wir brauchen einen BinaryOperator mit dem Typ TestObject . Auf traditionelle Weise wird es folgendermaßen implementiert:
BinaryOperator<TestObject> binary = new BinaryOperator<TestObject>() {
@Override
public TestObject apply(TestObject t, TestObject u) {
return t;
}
};
Wie Sie in der anonymen Implementierung sehen, sind zwei TestObject-Argumente erforderlich, und es wird auch ein TestObject-Objekt zurückgegeben. Um diese Bedingung mit dem ::Operator zu erfüllen, können wir mit einer statischen Methode beginnen:
public class TestObject {
public static final TestObject testStatic(TestObject t, TestObject t2){
return t;
}
}
und dann anrufen:
BinaryOperator<TestObject> binary = TestObject::testStatic;
Ok, es wurde gut kompiliert. Was ist, wenn wir eine Instanzmethode benötigen? Aktualisieren Sie TestObject mit der Instanzmethode:
public class TestObject {
public final TestObject testInstance(TestObject t, TestObject t2){
return t;
}
public static final TestObject testStatic(TestObject t, TestObject t2){
return t;
}
}
Jetzt können wir wie folgt auf die Instanz zugreifen:
TestObject testObject = new TestObject();
BinaryOperator<TestObject> binary = testObject::testInstance;
Dieser Code wird gut kompiliert, aber unter einem nicht:
BinaryOperator<TestObject> binary = TestObject::testInstance;
Meine Sonnenfinsternis sagt mir: "Es kann kein statischer Verweis auf die nicht statische Methode testInstance (TestObject, TestObject) vom Typ TestObject ... erstellt werden."
Fair genug, es ist eine Instanzmethode, aber wenn wir testInstancewie folgt überladen :
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;
}
}
Und Ruf an:
BinaryOperator<TestObject> binary = TestObject::testInstance;
Der Code wird einfach gut kompiliert. Weil es testInstancemit einem einzelnen Parameter anstelle eines doppelten aufgerufen wird . Ok, was ist mit unseren beiden Parametern passiert? Lass uns ausdrucken und sehen:
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;
}
}
Welches wird ausgegeben:
1418481495
303563356
Test instance called. this.hashCode:1418481495
Given parameter hashCode:303563356
Ok, JVM ist intelligent genug, um param1.testInstance (param2) aufzurufen. Können wir testInstancevon einer anderen Ressource verwenden, aber nicht von TestObject, dh:
public class TestUtil {
public final TestObject testInstance(TestObject t){
return t;
}
}
Und Ruf an:
BinaryOperator<TestObject> binary = TestUtil::testInstance;
Es wird einfach nicht kompiliert und der Compiler sagt: "Der Typ TestUtil definiert nicht testInstance (TestObject, TestObject)" . Der Compiler sucht also nach einer statischen Referenz, wenn es sich nicht um denselben Typ handelt. Ok, was ist mit Polymorphismus? Wenn wir endgültige Modifikatoren entfernen und unsere SubTestObject- Klasse hinzufügen :
public class SubTestObject extends TestObject {
public final TestObject testInstance(TestObject t){
return t;
}
}
Und Ruf an:
BinaryOperator<TestObject> binary = SubTestObject::testInstance;
Es wird auch nicht kompiliert, der Compiler sucht weiterhin nach statischen Referenzen. Aber der folgende Code wird gut kompiliert, da er einen Test besteht:
public class TestObject {
public SubTestObject testInstance(Object t){
return (SubTestObject) t;
}
}
BinaryOperator<TestObject> binary = TestObject::testInstance;
* Ich lerne gerade, also habe ich herausgefunden, indem ich versucht habe zu sehen, zögern Sie nicht, mich zu korrigieren, wenn ich falsch liege