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 testInstance
wie 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 testInstance
mit 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 testInstance
von 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