Poiché molte risposte qui spiegano bene il ::
comportamento, vorrei inoltre chiarire che l' ::
operatore non deve necessariamente avere la stessa firma dell'interfaccia funzionale di riferimento se viene utilizzato per le variabili di istanza . Supponiamo che abbiamo bisogno di un BinaryOperator che abbia un tipo di TestObject . In modo tradizionale è implementato in questo modo:
BinaryOperator<TestObject> binary = new BinaryOperator<TestObject>() {
@Override
public TestObject apply(TestObject t, TestObject u) {
return t;
}
};
Come vedi nell'implementazione anonima, sono necessari due argomenti TestObject e restituisce anche un oggetto TestObject. Per soddisfare questa condizione utilizzando l' ::
operatore possiamo iniziare con un metodo statico:
public class TestObject {
public static final TestObject testStatic(TestObject t, TestObject t2){
return t;
}
}
e quindi chiama:
BinaryOperator<TestObject> binary = TestObject::testStatic;
Ok, compilato bene. E se avessimo bisogno di un metodo di istanza? Consente di aggiornare TestObject con il metodo di istanza:
public class TestObject {
public final TestObject testInstance(TestObject t, TestObject t2){
return t;
}
public static final TestObject testStatic(TestObject t, TestObject t2){
return t;
}
}
Ora possiamo accedere all'istanza come di seguito:
TestObject testObject = new TestObject();
BinaryOperator<TestObject> binary = testObject::testInstance;
Questo codice viene compilato correttamente, ma sotto uno non:
BinaryOperator<TestObject> binary = TestObject::testInstance;
Dimmi la mia eclissi "Impossibile fare un riferimento statico al metodo non statico testInstance (TestObject, TestObject) dal tipo TestObject ..."
Abbastanza giusto è un metodo di istanza, ma se sovraccarichiamo testInstance
come di seguito:
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;
}
}
E chiama:
BinaryOperator<TestObject> binary = TestObject::testInstance;
Il codice verrà compilato correttamente. Perché chiamerà testInstance
con un singolo parametro invece di doppio. Ok, quindi cosa sono successi i nostri due parametri? Consente di stampare e vedere:
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;
}
}
Che produrrà:
1418481495
303563356
Test instance called. this.hashCode:1418481495
Given parameter hashCode:303563356
Ok, quindi JVM è abbastanza intelligente da chiamare param1.testInstance (param2). Possiamo usare testInstance
da un'altra risorsa ma non TestObject, ovvero:
public class TestUtil {
public final TestObject testInstance(TestObject t){
return t;
}
}
E chiama:
BinaryOperator<TestObject> binary = TestUtil::testInstance;
Semplicemente non verrà compilato e il compilatore dirà: "Il tipo TestUtil non definisce testInstance (TestObject, TestObject)" . Quindi il compilatore cercherà un riferimento statico se non è dello stesso tipo. Ok, che dire del polimorfismo? Se rimuoviamo i modificatori finali e aggiungiamo la nostra classe SubTestObject :
public class SubTestObject extends TestObject {
public final TestObject testInstance(TestObject t){
return t;
}
}
E chiama:
BinaryOperator<TestObject> binary = SubTestObject::testInstance;
Inoltre non verrà compilato, il compilatore cercherà comunque riferimenti statici. Ma sotto il codice verrà compilato bene poiché sta passando is-a test:
public class TestObject {
public SubTestObject testInstance(Object t){
return (SubTestObject) t;
}
}
BinaryOperator<TestObject> binary = TestObject::testInstance;
* Sto solo studiando, quindi ho capito provando a vedere, sentiti libero di correggermi se sbaglio