วิธีการอ้างอิงข้ามค่าใช้จ่ายของเสื้อคลุมแลมบ์ดา? พวกเขาอาจจะในอนาคตหรือไม่
อ้างอิงจากการสอนของ Java เกี่ยวกับวิธีการอ้างอิง :
บางครั้ง ... การแสดงออกแลมบ์ดาไม่ทำอะไรเลยนอกจากเรียกวิธีการที่มีอยู่ ในกรณีเหล่านั้นมักจะชัดเจนกว่าในการอ้างอิงถึงวิธีการที่มีอยู่ตามชื่อ การอ้างอิงวิธีใช้ทำให้คุณสามารถทำได้ มันเป็นแลมบ์ดาขนาดกะทัดรัดและอ่านง่ายสำหรับวิธีการที่มีชื่ออยู่แล้ว
ฉันชอบไวยากรณ์แลมบ์ดากับไวยากรณ์การอ้างอิงเมธอดด้วยเหตุผลหลายประการ:
แลมบ์ดานั้นชัดเจนขึ้น
แม้จะมีการอ้างสิทธิ์ของออราเคิล แต่ฉันพบว่าแลมบ์ดาไวยากรณ์นั้นง่ายต่อการอ่านมากกว่าการอ้างอิงวิธีการออบเจ็กต์สั้น ๆ เพราะไวยากรณ์การอ้างอิงเมธอดนั้นไม่ชัดเจน:
Bar::foo
คุณกำลังเรียกวิธีการหนึ่งอาร์กิวเมนต์คงที่ในชั้นเรียนของ x และผ่านมันได้หรือไม่
x -> Bar.foo(x)
หรือคุณกำลังเรียกวิธีการเป็นศูนย์อาร์กิวเมนต์บน x?
x -> x.foo()
ไวยากรณ์การอ้างอิงเมธอดสามารถยืนอยู่ได้ทั้งอันใดอันหนึ่ง มันซ่อนสิ่งที่รหัสของคุณกำลังทำอยู่
แลมบ์ดาปลอดภัยกว่า
หากคุณอ้างอิง Bar :: foo เป็นวิธีการเรียนและ Bar ภายหลังเพิ่มวิธีการตัวอย่างที่มีชื่อเดียวกัน (หรือในทางกลับกัน) รหัสของคุณจะไม่รวบรวมอีกต่อไป
คุณสามารถใช้ lambdas อย่างสม่ำเสมอ
คุณสามารถห่อฟังก์ชั่นใด ๆ ในแลมบ์ดา - เพื่อให้คุณสามารถใช้ไวยากรณ์เดียวกันได้ทุกที่ ไวยากรณ์การอ้างอิงเมธอดจะไม่ทำงานกับวิธีการที่ใช้หรือคืนค่าอาร์เรย์แบบดั้งเดิมโยนข้อยกเว้นที่ตรวจสอบหรือมีชื่อวิธีการเดียวกับที่ใช้เป็นอินสแตนซ์และวิธีการแบบสแตติก (เนื่องจากไวยากรณ์การอ้างอิงเมธอดนั้นไม่ชัดเจน . มันไม่ทำงานเมื่อคุณมีเมธอดมากเกินไปด้วยจำนวนอาร์กิวเมนต์ที่เท่ากัน แต่คุณไม่ควรทำเช่นนั้น (ดูรายการของ Josh Bloch ที่ 41) ดังนั้นเราจึงไม่สามารถระงับวิธีการดังกล่าวได้
ข้อสรุป
หากไม่มีประสิทธิภาพในการทำเช่นนั้นฉันถูกล่อลวงให้ปิดคำเตือนใน IDE ของฉันและใช้ไวยากรณ์แลมบ์ดาอย่างสม่ำเสมอโดยไม่ต้องโรยการอ้างอิงวิธีการเป็นครั้งคราวลงในรหัสของฉัน
PS
ไม่ว่าที่นี่หรือที่นั่น แต่ในความฝันของฉันการอ้างอิงวิธีวัตถุมีลักษณะเช่นนี้มากขึ้นและใช้การเรียกใช้แบบไดนามิกกับวิธีการโดยตรงบนวัตถุโดยไม่มีตัวห่อหุ้มแลมบ์ดา:
_.foo()
.map(_.acceptValue())
: ถ้าฉันไม่ผิดนี่ดูเหมือนว่าจะเป็นไวยากรณ์ของสกาล่า บางทีคุณอาจกำลังพยายามใช้ภาษาผิด
System.out::println
ไปforEach()
ตลอดเวลา ... ?