เนื่องจากคำตอบมากมายที่นี่อธิบายได้ดี ::
พฤติกรรมนอกจากนี้ผมอยากจะชี้แจงว่าจำเป็นที่จะต้องดำเนินการไม่ให้มีลายเซ็นเดียวกันตรงตามที่อินเตอร์เฟซการทำงานหมายถึงหากมีการใช้สำหรับตัวแปรเช่น::
ให้ถือว่าเราต้องBinaryOperatorซึ่งมีประเภทของTestObject ในแบบดั้งเดิมมันใช้งานเช่นนี้:
BinaryOperator<TestObject> binary = new BinaryOperator<TestObject>() {
@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<TestObject> 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<TestObject> binary = testObject::testInstance;
รหัสนี้คอมไพล์ได้ แต่ไม่ต่ำกว่า:
BinaryOperator<TestObject> binary = TestObject::testInstance;
อุปราคาของฉันบอกฉัน "ไม่สามารถทำการอ้างอิงแบบคงที่ไปยังวิธีการแบบไม่คงที่ testInstance (TestObject, 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<TestObject> binary = TestObject::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<TestObject> binary = TestUtil::testInstance;
มันก็จะไม่ได้รวบรวมและเรียบเรียงจะบอก: "ประเภท TestUtil ไม่ได้กำหนด testInstance (TestObject, TestObject)" คอมไพเลอร์จะมองหาการอ้างอิงแบบคงที่หากไม่ใช่ประเภทเดียวกัน ตกลงสิ่งที่เกี่ยวกับความหลากหลาย? หากเราลบตัวดัดแปลงสุดท้ายและเพิ่มคลาสSubTestObjectของเรา:
public class SubTestObject extends TestObject {
public final TestObject testInstance(TestObject t){
return t;
}
}
และโทร:
BinaryOperator<TestObject> binary = SubTestObject::testInstance;
มันจะไม่รวบรวมเช่นกันคอมไพเลอร์จะยังคงมองหาการอ้างอิงแบบคงที่ แต่รหัสด้านล่างจะรวบรวมได้ดีเพราะผ่านการทดสอบคือ:
public class TestObject {
public SubTestObject testInstance(Object t){
return (SubTestObject) t;
}
}
BinaryOperator<TestObject> binary = TestObject::testInstance;
* ฉันเพิ่งเรียนเพื่อที่ฉันจะได้คิดออกโดยลองและดูรู้สึกฟรีเพื่อแก้ไขฉันถ้าฉันผิด