การอ้างอิงเมธอดของอินสแตนซ์ใดก็ได้
อ้างอิงเมธอดอินสแตนซ์โดยไม่ระบุตัวรับ ซึ่งใช้บ่อยกับการทำงานของ Stream
การอ้างอิงเมธอดของอินสแตนซ์ใดก็ได้ เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
การอ้างอิงอินสแตนซ์ใดก็ได้คืออะไร
การอ้างอิงเมธอดของอินสแตนซ์ใดก็ได้ใช้ ClassName::instanceMethod โดย อาร์กิวเมนต์ตัวแรก ของอินเทอร์เฟซเชิงฟังก์ชันจะทำหน้าที่เป็นตัวรับ — แต่ละองค์ประกอบจะกลายเป็นออบเจ็กต์ที่เมธอดถูกเรียกใช้กับออบเจ็กต์นั้น
import java.util.*;
import java.util.stream.*;
List<String> names = List.of("alice","bob","carol");
// String::toUpperCase — receiver is each list element
List<String> upper = names.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(upper); // [ALICE, BOB, CAROL]การระบุตัวรับ
สำหรับการอ้างอิงอินสแตนซ์ใดก็ได้ Type::method พารามิเตอร์ตัวแรกของอินเทอร์เฟซเชิงฟังก์ชันจะกลายเป็น this (ตัวรับ):
// String::length matches Function<String, Integer>
// Equivalent to: s -> s.length()
Function<String, Integer> len = String::length;
System.out.println(len.apply("Java")); // 4
// String::isEmpty matches Predicate<String>
// Equivalent to: s -> s.isEmpty()
Predicate<String> isEmpty = String::isEmpty;
System.out.println(isEmpty.test("")); // trueใช้บ่อยกับการดำเนินการของสตรีม
การอ้างอิงอินสแตนซ์ใดก็ได้เป็นประเภทที่ใช้บ่อยที่สุดในสายงานสตรีม:
List<String> words = List.of("Hello","","World","","Java");
// filter with String::isEmpty
long empty = words.stream().filter(String::isEmpty).count();
System.out.println(empty); // 2
// map with String::toLowerCase
words.stream()
.filter(s -> !s.isEmpty())
.map(String::toLowerCase)
.forEach(System.out::println);รูปแบบ BiFunction กับเมธอดที่รับสองอาร์กิวเมนต์
เมธอดที่รับสองอาร์กิวเมนต์ของชนิดข้อมูลหนึ่งจะตรงกับ BiFunction<T, U, R> โดย T คือตัวรับ และ U คืออาร์กิวเมนต์:
import java.util.function.*;
// String::startsWith → BiPredicate<String, String>
// receiver=first arg, argument=second arg
BiPredicate<String, String> starts = String::startsWith;
System.out.println(starts.test("JavaStream", "Java")); // true
System.out.println(starts.test("Python", "Java")); // falseComparator กับอินสแตนซ์ใดก็ได้
String::compareTo ตรงกับ Comparator<String> — อาร์กิวเมนต์สองตัวของตัวเปรียบเทียบจะกลายเป็นตัวรับและพารามิเตอร์:
List<String> words = List.of("banana","apple","cherry");
List<String> sorted = words.stream()
.sorted(String::compareTo)
.collect(Collectors.toList());
System.out.println(sorted); // [apple, banana, cherry]อินสแตนซ์ใดก็ได้ของคลาสที่กำหนดเอง
ใช้งานได้กับเมธอดอินสแตนซ์ของคลาสใดก็ได้ ไม่จำกัดเฉพาะชนิดข้อมูลของ JDK:
record Product(String name, double price) {
boolean isExpensive() { return price > 50; }
String label() { return name + " ($" + price + ")"; }
}
List<Product> products = List.of(
new Product("Widget", 9.99),
new Product("Gadget", 99.99),
new Product("Donut", 1.50)
);
products.stream()
.filter(Product::isExpensive)
.map(Product::label)
.forEach(System.out::println); // Gadget ($99.99)ความแตกต่างจากอินสแตนซ์เฉพาะ
ความแตกต่างที่สำคัญ:
- เฉพาะ:
obj::method— obj เป็นตัวรับเสมอ - ใดก็ได้:
Type::method— แต่ละองค์ประกอบ IS ตัวรับ
String fixed = "prefix";
// Specific instance: fixed is always the receiver
Predicate<String> startsFixed = fixed::startsWith; // always checks 'prefix'.startsWith(arg)
// Arbitrary instance: each element is the receiver
Predicate<String> isEmpty = String::isEmpty; // each element.isEmpty()การอ้างอิงเมธอดในตัวรวบรวม
การอ้างอิงอินสแตนซ์ใดก็ได้ทำงานร่วมกับตัวรวบรวมได้อย่างเป็นธรรมชาติ:
List<String> items = List.of(" hello "," world "," java ");
List<String> trimmed = items.stream()
.map(String::trim)
.collect(Collectors.toList());
System.out.println(trimmed); // [hello, world, java]การเชื่อมการอ้างอิงเมธอด
สามารถเชื่อมการอ้างอิงเมธอดด้วย andThen/compose บน Function ได้:
Function<String, String> pipeline =
((Function<String, String>) String::trim)
.andThen(String::toUpperCase);
System.out.println(pipeline.apply(" hello world "));
// HELLO WORLDข้อควรระวัง: เมธอดที่มีชื่อซ้ำต่างลายเซ็น
เมื่อเมธอดมีหลายรูปแบบ คอมไพเลอร์ต้องอนุมานว่ารูปแบบใดตรงกับอินเทอร์เฟซเชิงฟังก์ชัน หากกำกวม จะเกิดข้อผิดพลาดในการคอมไพล์ — ใช้แลมบ์ดาเพื่อระบุให้ชัดเจน:
// println is overloaded — which one?
// Consumer<String> c = System.out::println; // OK — infers println(String)
// Consumer<Object> c2 = System.out::println; // OK
// But if ambiguous:
// Function<Object,?> fn = System.out::println; // Error — println doesn't return a valueประสิทธิภาพ
การอ้างอิงเมธอดและแลมบ์ดาจะถูกคอมไพล์เป็นไบต์โค้ดแบบเดียวกัน (ผ่าน invokedynamic) จึงไม่มีความแตกต่างด้านประสิทธิภาพ — ให้เลือกแบบที่อ่านเข้าใจได้มากกว่า โดยแนวทางรูปแบบการเขียนส่วนใหญ่มักแนะนำการอ้างอิงเมธอดเมื่อสามารถสื่อเจตนาได้อย่างชัดเจน
ตรวจสอบความเข้าใจอย่างรวดเร็ว
String::toUpperCase แทนอะไรเมื่อใช้ร่วมกับ .map()
ทบทวน: การอ้างอิงเมธอดของอินสแตนซ์ใดก็ได้
ประเด็นสำคัญ:
- ไวยากรณ์: ClassName::instanceMethod — แต่ละองค์ประกอบเป็นตัวรับ
- ตรงกับอินเทอร์เฟซเชิงฟังก์ชันที่ตัวรับเป็นพารามิเตอร์ตัวแรก
- ใช้บ่อยที่สุดใน .map(), .filter(), .sorted(), .forEach()
- เมธอดที่รับสองอาร์กิวเมนต์ → BiFunction/BiPredicate โดยมีองค์ประกอบเป็นตัวรับ
- ไม่มีความแตกต่างด้านประสิทธิภาพเมื่อเทียบกับแลมบ์ดา — ให้เลือกแบบที่อ่านเข้าใจได้มากกว่า
คำถามที่พบบ่อย
บทเรียน “การอ้างอิงเมธอดของอินสแตนซ์ใดก็ได้” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การอ้างอิงเมธอดของอินสแตนซ์ใดก็ได้” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การอ้างอิงเมธอดของอินสแตนซ์ใดก็ได้”
อ้างอิงเมธอดอินสแตนซ์โดยไม่ระบุตัวรับ ซึ่งใช้บ่อยกับการทำงานของ Stream คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การอ้างอิงเมธอดของอินสแตนซ์ใดก็ได้” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม
ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การอ้างอิงเมธอดแบบ Static
- การอ้างอิงเมธอดอินสแตนซ์บนอินสแตนซ์เฉพาะ
- การอ้างอิงเมธอดของอินสแตนซ์ใดก็ได้
- การอ้างอิงตัวสร้าง