การแนะนำสัญกรณ์แลมบ์ดาใหม่ (ดูตัวอย่างเช่นบทความนี้ ) ใน Java 8 จะต้องใช้การอนุมานบางประเภทหรือไม่?
ถ้าเป็นเช่นนั้นระบบประเภทใหม่จะส่งผลกระทบต่อภาษาจาวาโดยรวมอย่างไร
การแนะนำสัญกรณ์แลมบ์ดาใหม่ (ดูตัวอย่างเช่นบทความนี้ ) ใน Java 8 จะต้องใช้การอนุมานบางประเภทหรือไม่?
ถ้าเป็นเช่นนั้นระบบประเภทใหม่จะส่งผลกระทบต่อภาษาจาวาโดยรวมอย่างไร
คำตอบ:
มีข้อมูลที่ไม่ถูกต้องพอสมควรในคำตอบของวงล้อประหลาดและในกระทู้ความคิดเห็นของมัน ฉันจะตอบที่นี่ในคำตอบเนื่องจากความคิดเห็นมีขนาดเล็กเกินไป นอกจากนี้เนื่องจากคำตอบนี้หลังจากทั้งหมดฉันจะพยายามตอบคำถามเดิมด้วย (โปรดทราบว่าฉันไม่ใช่ผู้เชี่ยวชาญเกี่ยวกับระบบการพิมพ์)
อันดับแรกคำตอบสั้น ๆ สำหรับคำถามต้นฉบับคือใช่และไม่ใช่ใช่ Java 8 จะมีการอนุมานประเภทมากกว่า Java 7 และไม่มีไม่มีระบบพิมพ์ "ใหม่" ใน Java 8 แม้ว่าจะมีการเปลี่ยนแปลงเล็กน้อย .
Java 8 จะยังคงถูกพิมพ์แบบสแตติกและยังคงมีขั้วต่อระหว่างคลาสและอินเตอร์เฟส ไม่มีประเภทใหม่เช่นประเภทฟังก์ชั่น ชนิดของแลมบ์ดานั้นโดยพื้นฐานแล้วคือ "ส่วนต่อประสานการทำงาน" ซึ่งเป็นส่วนต่อประสานทั่วไปที่มีวิธีการทางนามธรรมเดียว
การเชื่อมต่อสามารถมีรหัสในรูปแบบของวิธีการเริ่มต้น แต่รูปแบบของการสืบทอดเดี่ยวของคลาสและการสืบทอดอินเทอร์เฟซหลายรายการยังคงเหมือนเดิม แน่นอนว่ามีการปรับเปลี่ยนบางอย่างเช่นกฎสำหรับการแก้ไขเมธอดในที่ที่มีเมธอดดีฟอลต์ แต่พื้นฐานไม่เปลี่ยนแปลง
ประเภทใดก็ตามที่อนุมานโดยการอนุมานประเภทสามารถเขียนออกมาได้อย่างชัดเจน ในการใช้ตัวอย่างของเฟืองล้อเฟือง
Collections.<MyClass>sort(list, (a, b) -> { return a.order - b.order; });
เป็นน้ำตาลสำหรับ
Collections.<MyClass>sort(list,
(Comparator<MyClass>)((MyClass a, MyClass b) -> { return a.order - b.order; }));
ดังนั้นการอนุมานของข้อความ " sparkleshy " จึงไม่ต้องการส่วนขยายของระบบประเภท "จึงถูกต้อง
แต่เพื่อกลับไปที่น้ำตาล syntactic ฉันจะทำซ้ำคำสั่งของฉันว่าการแสดงออกแลมบ์ดาไม่ได้เป็นน้ำตาล syntactic สำหรับชั้นในที่ไม่ระบุชื่อ Ratchet freak ระบุว่าการแสดงออกแลมบ์ดานั้นถูกแปลเป็นอินสแตนซ์คลาสภายในที่ไม่ระบุชื่อและ Sparkleshy ก็แค่ยืนยันว่าแลมบ์ดานั้นเป็นน้ำตาลซินแทคติกสำหรับคลาสภายในที่ไม่ระบุชื่อ แต่ข้อความเหล่านี้ไม่ถูกต้อง พวกเขาอาจขึ้นอยู่กับข้อมูลที่ล้าสมัย การใช้แลมบ์ดายุคแรก ๆ ได้ใช้แลมบ์ดาด้วยวิธีนี้ แต่สิ่งต่าง ๆ มีการเปลี่ยนแปลง
นิพจน์แลมบ์ดามีความแตกต่างทางความหมายจากคลาสภายในและมีการใช้งานแตกต่างจากคลาสภายใน
การแสดงออกของแลมบ์ดามีความแตกต่างทางความหมายจากคลาสภายในด้วยสองวิธี การประเมินการแสดงออกแลมบ์ดาไม่จำเป็นต้องสร้างอินสแตนซ์ใหม่ในแต่ละครั้ง พวกเขายังมีความหมายที่แตกต่างกันตัวอย่างเช่นพวกเขาจับภาพนี้แตกต่างกัน ในคลาสภายในนี่คืออินสแตนซ์ของคลาสภายในขณะที่ในแลมบ์ดานี่คืออินสแตนซ์ที่ปิดล้อม พิจารณาสิ่งต่อไปนี้:
public class CaptureThis {
void a(Runnable r) { r.run(); }
void b() {
a(new Runnable() { public void run() { System.out.println(this); }});
a(() -> System.out.println(this));
}
public String toString() { return "outer"; }
public static void main(String[] args) { new CaptureThis().b(); }
}
ในแลมบ์ดา JDK 8 รุ่นล่าสุด (ฉันใช้b69 ) ผลลัพธ์จะเป็นดังนี้:
CaptureThis$1@113de03
outer
นอกจากนี้แลมบ์ดานิพจน์ยังมีการใช้งานที่แตกต่างจากคลาสภายในอย่างสิ้นเชิง หากคุณเปรียบเทียบเอาท์พุทแยกส่วนคุณจะเห็นว่าโค้ดคลาสภายในตรงไปตรงมากับการสร้างและเรียกไปที่ตัวสร้างของ CaptureThis $ 1 ในขณะที่นิพจน์แลมบ์ดาจะคอมไพล์กับคำสั่งแบบอุทธรณ์ สำหรับคำอธิบายเต็มรูปแบบของวิธีการทำงานนี้และทำไมดูไบรอันเก๊' JavaOne 2012 พูดคุยแลมบ์ดา: แอบมองใต้กระโปรง
this
ด้วยMyClass.this