2012-06-21 23 views
16

Tôi nhận ra rằng việc triển khai lambda Java 8 có thể thay đổi, nhưng trong lambda build b39, tôi thấy rằng niềng răng chỉ có thể được bỏ qua khi biểu thức lambda trả về một kiểu không trống. Ví dụ, đây biên dịch:Khi nào là niềng răng tùy chọn trong cú pháp lambda Java 8?

public class Collections8 { 
     public static void main(String[] args) { 
       Iterable<String> names = Arrays.asList("Alice", "Bob", "Charlie"); 
       names.filter(e -> e.length() > 4).forEach(e -> { System.out.println(e); }); 
     } 
} 

Nhưng tháo niềng răng như thế này:

names.filter(e -> e.length() > 4).forEach(e -> System.out.println(e)); 

cung cấp cho các lỗi

Collections8.java:6: error: method forEach in interface Iterable<T> cannot be applied to given types; 
     names.filter(e -> e.length() > 4).forEach(e -> System.out.println(e)); 
             ^
    required: Block<? super String> 
    found: lambda 
    reason: incompatible return type void in lambda expression 
    where T is a type-variable: 
    T extends Object declared in interface Iterable 

bất cứ ai có thể giải thích những gì đang xảy ra ở đây?

+1

nếu nó vẫn đang được phát triển và có thể thay đổi tại sao thậm chí yêu cầu? câu trả lời có thể đã lỗi thời ngay lập tức. – user12345613

+10

Bởi vì tôi muốn hiểu lý do đằng sau nó. – hertzsprung

+1

bạn lấy phương pháp lọc từ đâu? Tôi có java 8 lambda versin, và mã yr không biên dịch. – NimChimpsky

Trả lời

18

Bạn có thể bỏ qua các dấu ngoặc ôm khi thân lambda là một biểu thức đơn lẻ hoặc lời gọi phương thức void. Mỗi biểu thức đánh giá một giá trị, và do đó không thể vô hiệu.

Nếu phần thân của lambda là một khối câu lệnh (ví dụ: một loạt các phép tính theo sau là câu lệnh return) hoặc lambda không có giá trị (nghĩa là loại trả về void) và không phải là một lời gọi phương thức void , bạn phải sử dụng biểu mẫu khối, yêu cầu dấu ngoặc đơn.

Trong lambda kiểu khối, nếu giá trị là return thì mọi đường dẫn mã có thể phải là return giá trị hoặc throw một Throwable.

+1

Tôi tin rằng đây chỉ là lặp lại những gì OP nói và thêm một số chi tiết bổ sung, mà không trả lời yêu cầu "tại sao", trừ khi tôi đang thiếu một cái gì đó. –

+0

Tôi nghĩ điều này làm rõ mọi thứ cho tôi. Các câu lệnh không phải là các biểu thức vì chúng không thể được đánh giá. Niềng răng là tùy chọn nếu cơ thể lambda là một biểu thức, nhưng chúng là bắt buộc nếu cơ thể là một câu lệnh hoặc một chuỗi các câu lệnh. Điều đó có đúng không, @jpm? – hertzsprung

+2

Gần. Cần làm rõ rằng các biểu thức là một loại câu lệnh (nghĩa là tất cả các biểu thức là các câu lệnh, nhưng không phải tất cả các câu lệnh đều là các biểu thức). Cũng lưu ý rằng một khối (mã được bao quanh bởi '{}') là, cú pháp, một câu lệnh đơn. Có thể nói rõ ràng rằng phần thân của một lambda có thể chứa một câu lệnh đơn, có thể là một biểu thức hoặc một câu lệnh khối. – jpm

10

Điều này chỉ ở: EG có (chủ yếu) đã đưa ra quyết định về cú pháp.

Sau khi xem xét một số giải pháp thay thế, chúng tôi đã quyết định về cơ bản áp dụng cú pháp C#. Chúng tôi vẫn có thể cân nhắc thêm về các điểm phạt (ví dụ: mũi tên mỏng so với mũi tên chất béo, dạng nilary đặc biệt, v.v.) và chưa chưa đưa ra quyết định về cú pháp tham chiếu phương pháp.

C# Cú pháp là:

lambda = ArgList Arrow Body 
ArgList = Identifier 
      | "(" Identifier [ "," Identifier ]* ")" 
      | "(" Type Identifier [ "," Type Identifier ]* ")" 
Body = Expression 
      | "{" [ Statement ";" ]+ "}" 

Một biểu thức ước lượng một cái gì đó, bạn không thể có biểu hiện khoảng trống trong Java. Đó là một tuyên bố, do đó bạn cần {} xung quanh nó.

http://mail.openjdk.java.net/pipermail/lambda-dev/2011-September/003936.html

0

Nếu không có dấu ngoặc, các lambda tự động trả về một biểu thức sau -> điều hành.
Vì vậy, khi bạn có một lambda không trả về gì, bạn phải sử dụng dấu ngoặc đơn

1

Tôi đã thử mã của bạn và phiên bản JRE cập nhật nhất mà tôi nghĩ rằng nó sẽ ổn.

Sau đây là những gì tôi tham chiếu từ tài liệu Java Java.

Trong biểu thức lambda, bạn phải kèm theo câu lệnh trong dấu ngoặc đơn ({}). Tuy nhiên, bạn không phải kèm theo một lời gọi phương thức void trong niềng răng.
Ví dụ, sau đây là một biểu thức lambda hợp lệ:

email -> System.out.println(email) 

Và doc giải thích khá rõ ràng. Hy vọng điều này có thể giải quyết vấn đề của bạn.

Tham chiếu: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html

Các vấn đề liên quan