2015-03-06 41 views
5

Tôi đang cố gắng bảo toàn thông tin kiểu chung từ kiểu trả về của biểu thức lambda trên một số hàm bậc cao hơn trong Java 8. Tôi đã đơn giản hóa mã thực của tôi xuống thử nghiệm này trường hợp. Vấn đề không phải là những gì tôi mong đợi mã để làm chính xác, nhưng thay vì tôi mong đợi các loại chung (s) R được suy ra như java.lang.String và thực hiện thông qua các cuộc gọi chức năng.Java 8 - Suy ra kiểu trả về chung với lambdas

import java.util.function.Function; 

public class AdamTest { 

    public final static void main(final String args[]) { 
     final AdamTest adamTest = new AdamTest(); 

     final String s = adamTest.thing2(7).apply(i -> i.toString()); 
     System.out.println(s); 
    } 


    private <R> R fn1(final Function<Integer, R> op) { 
     return op.apply(10); 
    } 

    private <R> Function<Function<Integer, R>, R> thing2(final Integer val) { 
     return fn1(i -> new Function<Function<Integer, R>, R>() { 
       @Override 
       public R apply(Function<Integer, R> op) { 
        return op.apply(val * i); 
       } 
      } 
     ); 
    } 
} 

Hiện tại mã này không biên dịch vì dòng này final String s = adamTest.thing2(7).apply(i -> i.toString());. Tôi nghĩ rằng tôi có một cái gì đó tinh tế sai với giới hạn loại của tôi, như trình biên dịch dường như không thể suy ra kiểu trả về của thing2(7).apply và báo cáo Object thay vì String mà tôi đã hy vọng.

Làm thế nào để giới hạn loại generic chính xác để các kiểu trả về đúng nghĩa java.lang.String được suy bởi trình biên dịch?

+0

Bạn có thể thêm lỗi bạn đang nhận được không? –

+1

Trình biên dịch "đánh giá" biểu thức từ trái sang phải; Vấn đề xảy ra tại 'adamTest.thing2 (7)'. Trình biên dịch không nhìn vào '.apply' để tìm ra kiểu, và nếu không có nó thì không thể. –

+0

Bạn đang cố gắng làm gì chính xác? Điều này là hoàn toàn không rõ ràng. – fge

Trả lời

5

Như đã nói, những phát biểu được đánh giá từ trái sang phải.

Để buộc các trình biên dịch sử dụng đúng loại, bạn chỉ có thể viết nó như

final String s = adamTest.<String>thing2(7).apply(String::valueOf); 

EDIT: Theo các ý kiến, khái niệm lambda có thể được thay thế bằng một tài liệu tham khảo phương pháp (có vẻ sạch hơn).

+0

Ngoài ra, bạn có thể thay thế cuộc gọi phương thức thành i.toString() bằng tham chiếu phương thức. – buftlica

+0

@MatkoMedenjak Thật không may là không thể làm được. Lớp 'Integer' định nghĩa hai phương thức có tên là' toString': một phương thức tĩnh ['Integer.toString (int)'] (http://docs.oracle.com/javase/8/docs/api/java/lang/ Integer.html # toString-int-) và một phương thức không tĩnh ['Integer.toString()'] (http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html # toString--). Trình biên dịch không thể phân biệt giữa chúng nếu sử dụng tham chiếu phương thức 'Integer :: toString'. – Seelenvirtuose

+0

Cảm ơn @Seelenvirtuose đây là giải pháp tôi đến với bản thân mình, nhưng bằng cách nào đó tôi thực sự mong đợi hội nghị tốt hơn từ trình biên dịch và cảm thấy rằng tôi đã mắc sai lầm trong generics của tôi, đó là lý do tại sao tôi hỏi câu hỏi. – adamretter

5

Tôi không nghĩ rằng nó có thể được sửa mà không có phôi (có thể ai đó biết rõ hơn). Một cách khác là chia báo cáo của mình theo hai dòng:

Function<Function<Integer, String>, String> thing2 = adamTest.thing2(7); 
final String s = thing2.apply(i -> i.toString()); 

Cũng lưu ý rằng thing2 có thể được đơn giản hóa:

private <R> Function<Function<Integer, R>, R> thing2(final Integer val) { 
    return fn1(i -> (op -> op.apply(val * i))); 
} 
+0

Tôi sẽ chia thành hai câu lệnh nếu có loại 'tự động' trong Java, nhưng vì tôi không thích sử dụng diễn viên chung được đề xuất bởi @Seelenvirtuose. Tôi thích sự đơn giản hóa, cảm ơn. – adamretter

-2

Bạn cần chuyển đến cài đặt của trình biên dịch để BẬT biểu thức lambda. Đây là một ví dụ với intellij. It's under file> Cấu trúc dự án, sau đó thả xuống này. Hy vọng điều này sẽ hữu ích!

nvm, không đủ danh tiếng. Nhưng tôi đã đưa ra chi tiết.

+0

Đủ danh tiếng để đăng hình ảnh * – Jahhein

+0

Bạn luôn có thể đăng hình ảnh trong một số máy chủ lưu trữ hình ảnh và liên kết chia sẻ. Những người dùng khác có danh tiếng cao hơn có thể chỉnh sửa bài đăng của bạn để đưa hình ảnh trực tiếp vào câu trả lời của bạn. – Pshemo

+0

Cảm ơn bạn, tôi sẽ chỉ đợi cho đến khi tôi có 10 danh tiếng. Các hướng dẫn khá thẳng về phía trước tôi nghĩ. Tôi nhìn thấy rất nhiều câu hỏi về lambda, và đó thường là câu trả lời. – Jahhein

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