1. ภาพรวม
การเปลี่ยนแปลงที่น่ายินดีที่สุดอย่างหนึ่งใน Java 8 คือการนำนิพจน์แลมบ์ดามาใช้เนื่องจากสิ่งเหล่านี้ช่วยให้เราสามารถละทิ้งคลาสที่ไม่ระบุตัวตนได้ช่วยลดรหัสสำเร็จรูปและปรับปรุงความสามารถในการอ่าน
อ้างอิงวิธีที่เป็นชนิดพิเศษของการแสดงออกแลมบ์ดา มักใช้เพื่อสร้างนิพจน์แลมบ์ดาอย่างง่ายโดยอ้างอิงวิธีการที่มีอยู่
การอ้างอิงวิธีการมีสี่ประเภท:
- วิธีการคงที่
- วิธีการอินสแตนซ์ของออบเจ็กต์เฉพาะ
- วิธีการอินสแตนซ์ของออบเจ็กต์ที่กำหนดเองประเภทใดประเภทหนึ่ง
- ตัวสร้าง
ในบทช่วยสอนนี้เราจะสำรวจการอ้างอิงเมธอดใน Java
2. อ้างอิงถึงวิธีการแบบคงที่
เราจะเริ่มต้นด้วยตัวอย่างง่ายๆการใช้ตัวพิมพ์ใหญ่และการพิมพ์รายการสตริง :
List messages = Arrays.asList("hello", "baeldung", "readers!");
เราสามารถบรรลุสิ่งนี้ได้โดยใช้ประโยชน์จากนิพจน์แลมบ์ดาอย่างง่ายที่เรียกเมธอดStringUtils.capitalize ()โดยตรง:
messages.forEach(word -> StringUtils.capitalize(word));
หรือเราสามารถใช้การอ้างอิงวิธีการเพื่ออ้างถึงวิธีการแบบคงที่เป็นตัวพิมพ์ใหญ่ :
messages.forEach(StringUtils::capitalize);
สังเกตว่าการอ้างอิงเมธอดจะใช้ตัวดำเนินการ::เสมอ
3. การอ้างอิงถึงวิธีการอินสแตนซ์ของวัตถุเฉพาะ
เพื่อแสดงการอ้างอิงประเภทนี้ลองพิจารณาสองคลาส:
public class Bicycle { private String brand; private Integer frameSize; // standard constructor, getters and setters } public class BicycleComparator implements Comparator { @Override public int compare(Bicycle a, Bicycle b) { return a.getFrameSize().compareTo(b.getFrameSize()); } }
และสร้างวัตถุBicycleComparatorเพื่อเปรียบเทียบขนาดเฟรมจักรยาน:
BicycleComparator bikeFrameSizeComparator = new BicycleComparator();
เราสามารถใช้นิพจน์แลมบ์ดาเพื่อจัดเรียงจักรยานตามขนาดเฟรม แต่เราต้องระบุจักรยานสองคันเพื่อเปรียบเทียบ:
createBicyclesList().stream() .sorted((a, b) -> bikeFrameSizeComparator.compare(a, b));
แต่เราสามารถใช้การอ้างอิงเมธอดเพื่อให้คอมไพเลอร์จัดการพารามิเตอร์ส่งผ่านให้เรา:
createBicyclesList().stream() .sorted(bikeFrameSizeComparator::compare);
การอ้างอิงวิธีการนั้นสะอาดกว่าและอ่านง่ายกว่ามากเนื่องจากโค้ดแสดงความตั้งใจของเราอย่างชัดเจน
4. การอ้างอิงถึงวิธีการอินสแตนซ์ของวัตถุโดยพลการของประเภทเฉพาะ
การอ้างอิงเมธอดประเภทนี้คล้ายกับตัวอย่างก่อนหน้านี้ แต่ไม่ต้องสร้างอ็อบเจ็กต์แบบกำหนดเองเพื่อทำการเปรียบเทียบ
มาสร้างรายการจำนวนเต็มที่เราต้องการจัดเรียง:
List numbers = Arrays.asList(5, 3, 50, 24, 40, 2, 9, 18);
หากเราใช้นิพจน์แลมบ์ดาแบบคลาสสิกจำเป็นต้องส่งผ่านพารามิเตอร์ทั้งสองอย่างชัดเจนในขณะที่การใช้การอ้างอิงเมธอดนั้นตรงไปตรงมากว่ามาก:
numbers.stream() .sorted((a, b) -> a.compareTo(b)); numbers.stream() .sorted(Integer::compareTo);
แม้ว่าจะยังคงเป็นซับเดียว แต่การอ้างอิงวิธีการนั้นอ่านและเข้าใจได้ง่ายกว่ามาก
5. การอ้างอิงถึงตัวสร้าง
เราสามารถอ้างอิงตัวสร้างในลักษณะเดียวกับที่เราอ้างถึงวิธีการแบบคงที่ในตัวอย่างแรกของเรา ข้อแตกต่างเพียงอย่างเดียวคือเราจะใช้คำหลักใหม่
มาสร้างอาร์เรย์จักรยานจากรายการสตริงด้วยแบรนด์ต่างๆ:
List bikeBrands = Arrays.asList("Giant", "Scott", "Trek", "GT");
ขั้นแรกเราจะเพิ่มตัวสร้างใหม่ในคลาสBicycleของเรา:
public Bicycle(String brand) { this.brand = brand; this.frameSize = 0; }
ต่อไปเราจะใช้ตัวสร้างใหม่ของเราจากการอ้างอิงวิธีการและสร้างอาร์เรย์จักรยานจากรายการสตริงเดิม:
bikeBrands.stream() .map(Bicycle::new) .toArray(Bicycle[]::new);
สังเกตว่าเราเรียกทั้งตัวสร้างBicycleและArrayโดยใช้การอ้างอิงวิธีการทำให้โค้ดของเราดูกระชับและชัดเจนมากขึ้น
6. ตัวอย่างและข้อ จำกัด เพิ่มเติม
ดังที่เราได้เห็นมาแล้วการอ้างอิงวิธีการเป็นวิธีที่ยอดเยี่ยมในการทำให้รหัสและความตั้งใจของเราชัดเจนและอ่านง่าย อย่างไรก็ตามเราไม่สามารถใช้มันเพื่อแทนที่นิพจน์แลมด้าทุกชนิดได้เนื่องจากมีข้อ จำกัด บางประการ
ข้อ จำกัด หลักของพวกเขาคือผลของสิ่งที่ยังแข็งแรงที่ยิ่งใหญ่ที่สุดของพวกเขาเอาท์พุทจากความต้องการแสดงออกก่อนหน้านี้เพื่อให้ตรงกับการป้อนพารามิเตอร์ของลายเซ็นวิธีอ้างอิง
ลองดูตัวอย่างข้อ จำกัด นี้:
createBicyclesList().forEach(b -> System.out.printf( "Bike brand is '%s' and frame size is '%d'%n", b.getBrand(), b.getFrameSize()));
กรณีง่ายๆนี้ไม่สามารถแสดงด้วยการอ้างอิงเมธอดได้เนื่องจากเมธอดprintfต้องการพารามิเตอร์ 3 ตัวในกรณีของเราและการใช้createBicyclesList () forEach ()จะอนุญาตให้การอ้างอิงเมธอดอนุมานพารามิเตอร์เดียวเท่านั้น ( อ็อบเจกต์Bicycle )
สุดท้ายเรามาดูวิธีสร้างฟังก์ชัน no-operation ที่สามารถอ้างอิงได้จากนิพจน์แลมบ์ดา
ในกรณีนี้เราต้องการใช้นิพจน์แลมบ์ดาโดยไม่ต้องใช้พารามิเตอร์
ขั้นแรกให้สร้างเมธอดdoNothingAtAll :
private static void doNothingAtAll(Object... o) { }
เนื่องจากเป็นวิธีการ varargs จึงทำงานในนิพจน์แลมบ์ดาไม่ว่าวัตถุที่อ้างอิงหรือจำนวนพารามิเตอร์จะถูกอนุมานก็ตาม
ตอนนี้เรามาดูการใช้งานจริง:
createBicyclesList() .forEach((o) -> MethodReferenceExamples.doNothingAtAll(o));
7. สรุป
ในบทช่วยสอนฉบับย่อนี้เราได้เรียนรู้ว่าการอ้างอิงวิธีการใดใน Java และวิธีใช้เพื่อแทนที่นิพจน์แลมบ์ดาจึงช่วยเพิ่มความสามารถในการอ่านและชี้แจงเจตนาของโปรแกรมเมอร์
โค้ดทั้งหมดที่นำเสนอในบทความนี้มีอยู่บน GitHub