Việc giới thiệu ký hiệu lambda mới (xem ví dụ bài viết này ) trong Java 8 sẽ yêu cầu một số loại suy luận?
Nếu vậy, hệ thống kiểu mới sẽ tác động đến toàn bộ ngôn ngữ Java như thế nào?
Việc giới thiệu ký hiệu lambda mới (xem ví dụ bài viết này ) trong Java 8 sẽ yêu cầu một số loại suy luận?
Nếu vậy, hệ thống kiểu mới sẽ tác động đến toàn bộ ngôn ngữ Java như thế nào?
Câu trả lời:
Có một chút thông tin không chính xác trong câu trả lời của ratchet freak và trong luồng nhận xét của nó. Tôi sẽ trả lời ở đây trong một câu trả lời, vì một nhận xét quá nhỏ. Ngoài ra, vì đây là câu trả lời cho tất cả, tôi cũng sẽ cố gắng trả lời câu hỏi ban đầu. (Lưu ý tuy nhiên tôi không phải là chuyên gia về các hệ thống loại.)
Đầu tiên, các câu trả lời ngắn cho câu hỏi ban đầu là Có và Không. Có, Java 8 sẽ có suy luận kiểu nhiều hơn đáng kể so với Java 7 và Không, không có hệ thống loại "mới" trong Java 8, mặc dù có một số thay đổi nhỏ .
Java 8 sẽ vẫn được gõ tĩnh và nó vẫn sẽ có sự phân đôi giữa các lớp và giao diện. Không có loại mới như loại chức năng. Loại lambda về cơ bản là một "giao diện chức năng" là một giao diện thông thường với một phương thức trừu tượng duy nhất.
Các giao diện bây giờ có thể có mã dưới dạng các phương thức mặc định, nhưng mô hình kế thừa đơn của các lớp và nhiều kế thừa của các giao diện vẫn giống nhau. Tất nhiên, có một số điều chỉnh, chẳng hạn như các quy tắc để giải quyết phương thức với sự có mặt của các phương thức mặc định, nhưng các nguyên tắc cơ bản là không thay đổi.
Bất kỳ loại nào được suy luận theo loại suy luận có thể được viết ra một cách rõ ràng. Để sử dụng ví dụ của ratchet freak ,
Collections.<MyClass>sort(list, (a, b) -> { return a.order - b.order; });
về cơ bản là đường cho
Collections.<MyClass>sort(list,
(Comparator<MyClass>)((MyClass a, MyClass b) -> { return a.order - b.order; }));
Vì vậy, tuyên bố "kiểu suy luận kiểu lấp lánh không yêu cầu bất kỳ sự mở rộng nào của hệ thống kiểu" về cơ bản là chính xác.
Nhưng để trở về đường cú pháp, tôi sẽ lặp lại tuyên bố của mình rằng biểu thức lambda không phải là đường cú pháp cho một lớp bên trong ẩn danh. Ratchet freak tuyên bố rằng một biểu thức lambda được dịch thành một khởi tạo lớp bên trong ẩn danh và Sparkleshy chỉ đơn giản xác nhận lại rằng lambda là đường cú pháp cho một lớp bên trong ẩn danh, nhưng những tuyên bố này không chính xác. Họ có thể dựa trên thông tin lỗi thời. Việc triển khai lambda sớm đã thực hiện lambdas theo cách này, nhưng mọi thứ đã thay đổi.
Các biểu thức Lambda khác biệt về mặt ngữ nghĩa với các lớp bên trong và chúng được triển khai khác với các lớp bên trong.
Các biểu thức Lambda khác biệt về mặt ngữ nghĩa với các lớp bên trong theo một vài cách. Đánh giá một biểu thức lambda không cần phải tạo một thể hiện mới mỗi lần. Họ cũng có ngữ nghĩa chụp khác nhau, ví dụ, họ nắm bắt điều này khác nhau. Trong một lớp bên trong, đây là thể hiện của lớp bên trong, trong khi trong lambda, đây là thể hiện kèm theo. Hãy xem xét những điều sau đây:
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(); }
}
Trong bản dựng lambda JDK 8 gần đây (tôi đã sử dụng b69 ), đầu ra sẽ giống như sau:
CaptureThis$1@113de03
outer
Hơn nữa, các biểu thức lambda được thực hiện hoàn toàn khác với các lớp bên trong. Nếu bạn so sánh đầu ra được phân tách, bạn sẽ thấy rằng mã lớp bên trong dễ dàng biên dịch với việc tạo và gọi tới một hàm tạo của Capture This $ 1, trong khi biểu thức lambda biên dịch thành một lệnh được kích hoạt có nghĩa là Runnable thông qua nghĩa là không xác định. Để được giải thích đầy đủ về cách thức hoạt động của nó và tại sao, hãy xem bài nói về JavaOne 2012 của Brian Goetz : Lambda: A Peek Under The Hood .
this
vớiMyClass.this