Burada birçok cevap iyi ::
davranışı açıkladığından , ek olarak ::
operatörün, örnek değişkenler için kullanılıyorsa, atıfta bulunan Fonksiyonel Arayüz ile tam olarak aynı imzası olması gerekmediğini açıklığa kavuşturmak istiyorum . Biz gerek varsayalım BinaryOperator türünü sahiptir testObject . Geleneksel olarak bu şekilde uygulanır:
BinaryOperator<TestObject> binary = new BinaryOperator<TestObject>() {
@Override
public TestObject apply(TestObject t, TestObject u) {
return t;
}
};
Anonim uygulamada gördüğünüz gibi iki TestObject argümanı gerektirir ve bir TestObject nesnesi de döndürür. Bu koşulu ::
operatörü kullanarak karşılamak için statik bir yöntemle başlayabiliriz:
public class TestObject {
public static final TestObject testStatic(TestObject t, TestObject t2){
return t;
}
}
ve sonra arayın:
BinaryOperator<TestObject> binary = TestObject::testStatic;
Tamam iyi derlenmiş. Bir örnek yöntemine ihtiyacımız olursa ne olur? TestObject öğesini örnek yöntemiyle güncelleyelim:
public class TestObject {
public final TestObject testInstance(TestObject t, TestObject t2){
return t;
}
public static final TestObject testStatic(TestObject t, TestObject t2){
return t;
}
}
Şimdi örneğe aşağıdaki gibi erişebiliriz:
TestObject testObject = new TestObject();
BinaryOperator<TestObject> binary = testObject::testInstance;
Bu kod iyi derler, ancak bir tanesinin altında değil:
BinaryOperator<TestObject> binary = TestObject::testInstance;
Tutulmam bana "TestObject türünden statik olmayan yöntem testInstance (TestObject, TestObject) statik başvuru yapamaz ..."
Yeterince adil bir örnek yöntemi, ancak testInstance
aşağıdaki gibi aşırı yüklerseniz:
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;
}
}
Ve Çağrı yap:
BinaryOperator<TestObject> binary = TestObject::testInstance;
Kod iyi derlenecektir. Çünkü testInstance
çift bir yerine tek bir parametre ile çağıracaktır . Peki iki parametremiz ne oldu? Çıktıya izin verir ve bkz:
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;
}
}
Hangi çıktı:
1418481495
303563356
Test instance called. this.hashCode:1418481495
Given parameter hashCode:303563356
Tamam, JVM param1.testInstance (param2) öğesini çağırmak için yeterince akıllıdır. testInstance
TestObject yerine başka bir kaynaktan kullanabilir miyiz, yani:
public class TestUtil {
public final TestObject testInstance(TestObject t){
return t;
}
}
Ve Çağrı yap:
BinaryOperator<TestObject> binary = TestUtil::testInstance;
Sadece derlemez ve derleyici şunu söyler: "TestUtil türü testInstance (TestObject, TestObject) tanımlamaz" . Dolayısıyla, derleyici aynı türde değilse statik bir başvuru arar. Tamam, polimorfizm ne olacak? Son değiştiricileri kaldırır ve SubTestObject sınıfımızı eklersek :
public class SubTestObject extends TestObject {
public final TestObject testInstance(TestObject t){
return t;
}
}
Ve Çağrı yap:
BinaryOperator<TestObject> binary = SubTestObject::testInstance;
Derleyici de olmayacak, derleyici hala statik referans arayacaktır. Ancak aşağıdaki kod geçtiği için iyi bir derleme olacaktır-bir test:
public class TestObject {
public SubTestObject testInstance(Object t){
return (SubTestObject) t;
}
}
BinaryOperator<TestObject> binary = TestObject::testInstance;
* Sadece okuyorum bu yüzden anlamaya çalıştım, yanılıyorsam beni düzeltmekten çekinmeyin