1. วิธีฟังก์ชัน

หากอินเทอร์เฟซมีเมธอดเดียวตัวแปรของประเภทอินเทอร์เฟซนั้นสามารถกำหนดค่าที่กำหนดโดยนิพจน์แลมบ์ดา (ฟังก์ชันแลมบ์ดา) อินเทอร์เฟซดังกล่าวกลายเป็นที่รู้จักในฐานะอินเทอร์เฟซการทำงาน (หลังจาก Java เพิ่มการสนับสนุนสำหรับฟังก์ชันแลมบ์ดา)

ตัวอย่างเช่น Java มีConsumer<Type>อินเทอร์เฟซซึ่งมีaccept(Type obj)เมธอด เหตุใดจึงจำเป็นต้องใช้อินเทอร์เฟซนี้

ใน Java 8 คอลเล็กชันมีforEach()เมธอดที่ให้คุณดำเนินการบางอย่าง กับแต่ละ องค์ประกอบของคอลเล็กชัน และนี่Consumer<T>คือส่วนต่อประสานการทำงานที่ใช้เพื่อส่งการกระทำไปยังforEach()เมธอด

วิธีแสดงองค์ประกอบทั้งหมดของคอลเล็กชัน มี ดังนี้

ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "Hello", "how's", "life?");

list.forEach( (s) -> System.out.println(s) );
การแสดงองค์ประกอบทั้งหมดของคอลเลกชัน (โดยใช้การแสดงออกของแลมบ์ดา)

คอมไพเลอร์จะแปลงโค้ดด้านบนเป็นโค้ดด้านล่าง:

ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "Hello", "how's", "life?");

list.forEach(new Consumer<String>()
{
   public void accept(String s)
   {
      System.out.println(s));
   }
});
การแสดงองค์ประกอบทั้งหมดของคอลเลกชัน (โดยใช้คลาสที่ไม่ระบุชื่อ)

รุ่นแรกสั้นกว่ารุ่นที่สองแน่นอน และแม้ว่าโค้ดที่มีนิพจน์แลมบ์ดาจะอ่านยาก แต่โค้ดที่มีคลาสภายในที่ไม่ระบุชื่อก็อ่านยากกว่าในบางครั้ง



2. วิธีการอ้างอิง

อย่างไรก็ตาม โค้ด นิพจน์แลมบ์ดา ของเรา สามารถเขียนให้สั้นกว่านี้ได้อีก

ขั้นแรก คุณสามารถละเว้นวงเล็บรอบsพารามิเตอร์:

list.forEach( (s) -> System.out.println(s) );
ก่อน
list.forEach( s -> System.out.println(s) );
หลังจาก

สามารถทำได้ก็ต่อเมื่อมีพารามิเตอร์ เดียว เท่านั้น หากมีหลายพารามิเตอร์คุณต้องใช้วงเล็บ

และอย่างที่สอง คุณสามารถเขียนได้ดังนี้:

list.forEach( System.out::println );
สัญกรณ์ที่กะทัดรัดที่สุด

นี่คือสัญกรณ์เดียวกันทุกประการ โปรดทราบว่าไม่มีวงเล็บprintlnหลัง

ที่นี่เรามีรหัสเดียวกัน — การเรียกใช้เมธอด:

object::method
x -> object.method(x)

ลองคิดดู: เราต้องการดำเนินการบางอย่างกับแต่ละองค์ประกอบของlistคอลเลกชัน หากการกระทำเป็นการเรียกใช้ฟังก์ชันเดียว (เช่นprintln()) คุณควรส่งฟังก์ชันไปยังเมธอดเป็นพารามิเตอร์

แต่เราจะอธิบายให้คอมไพเลอร์ฟังได้อย่างไรว่าเราต้องการส่งผ่านเมธอดมากกว่าเรียกมัน? ในการทำเช่นนี้ แทนที่จะใช้ตัวดำเนินการจุด เราใช้เครื่องหมายทวิภาคสองตัวนำหน้าชื่อเมธอด มีการใช้ทวิภาคเดียวเพื่อระบุตัวดำเนินการที่ประกอบไปด้วย

นี่เป็นสัญกรณ์ที่ง่ายและกะทัดรัดที่สุด



3. ตัวสร้าง

การอ้างอิงเมธอดด้วยทวิภาคคู่มีประโยชน์มากเมื่อเราทำงานกับสตรีม I/O คุณจะเห็นสิ่งนี้ในภายหลัง

ในระหว่างนี้ เรามาพูดถึงวิธียอดนิยม 3 วิธีในการส่งการอ้างอิงเมธอด:

การอ้างอิงถึงวิธีการของวัตถุ

ในการส่งการอ้างอิงไปยังเมธอดของอ็อบเจกต์ คุณต้องเขียนบางอย่างเช่น รหัสนี้เทียบเท่ากับ.object::method
x -> object.method(x)

พิเศษthisและsuperตัวแปรสามารถใช้เป็นวัตถุ

อ้างอิงถึงเมธอดของคลาส

ในการส่งการอ้างอิงไปยังเมธอดแบบสแตติก คุณต้องเขียนบางอย่างเช่น รหัสนี้ได้รับการแปลงเป็นรหัสเช่นclass::methodx -> class.method(x);

การอ้างอิงถึงตัวสร้าง

คอนสตรัคเตอร์ทำงานคล้ายกับเมธอดของคลาสสแตติก ดังนั้นคุณจึงสามารถส่งการอ้างอิงไปยังคอนสตรัคเตอร์ได้ นี่คือลักษณะ: .class::new

ตัวอย่างเช่น คุณสามารถหลีกเลี่ยงการลบประเภทสำหรับคอลเล็กชันและส่งต่อtoArray()เมธอดไปยังตัวสร้างที่จะสร้างอาร์เรย์ที่ต้องการ:toArray(int[]::new);