2015-01-22 17 views
8

Giống như một dự án nhỏ, tôi đã cố gắng tạo một thứ wee đọc lambdas được tuần tự hóa (cục bộ hoặc từ FTP) và gọi các hàm chạy của chúng như một phần của thử nghiệm để thử nghiệm với các liên kết tệp trong Windows (tức là mở một số loại tệp nhất định sẽ mở chúng bằng một chương trình nhất định) và không có gì, nhưng không có vấn đề gì tôi thử, nó dường như không bao giờ deserialize đúng cách.Không thể deserialize lambda

Lambda được tuyên bố như vậy

Runnable r = (Runnable & Serializable)() -> { 
    // blah blah 
    // made sure not to capture anything 
}; 

và tuần tự sử dụng một FileOutputStream bọc bởi một [n tùy chọn] BufferedOutputStream bọc bởi một ObjectOutputStream mà không vấn đề. Tuy nhiên, khi deserialized [trong một dự án khác nhau], nó không thành công, nói rằng nó không thể tìm thấy các lớp bao quanh chứa mã để serializing nó. Tôi đã thử những thứ khác nhau như gói chúng trong một lớp serializable (w/serialVersionUID = 0L cho mục đích thử nghiệm) hoặc xác định một giao diện mở rộng Runnable và Serializable, nhưng vô ích. Có, tôi biết rằng serializing lambdas không thực sự tốt (hoặc vì vậy chúng tôi đang nói), nhưng tôi không chắc chắn làm thế nào để đi về chuyển chức năng và chương trình con vào một cái gì đó tôi có thể lưu trữ như một tập tin hoặc trong một FTP. Nếu điều này thậm chí không đúng cách, hãy nói.

Ồ, tôi đang sử dụng Eclipse Luna của bất kỳ phiên bản mới nhất nào.

Edit:

deserialized như vậy

File f = new File(somePath); 
FileInputStream fish = new FileInputStream(f); 
BufferedInputStream bos = new BufferedInputStream(fish); // not really necessary 
ObjectInputStream ois = new ObjectInputStream(bos); 
Runnable r = (Runnable) ois.readObject(); 
ois.close(); 
r.run(); 
+0

Chờ bạn đang cố gắng sắp xếp một Phương thức? –

+0

Đối tượng phương thức không thể tuần tự hóa được. Tôi đang nói về một lambda Runnable. –

+1

Bạn có thể cho chúng tôi thấy mã tuần tự hóa/deserialization của bạn không? –

Trả lời

11

Bạn không thể deserialize một đối tượng mà không có lớp xác định nó. Điều này đã không thay đổi với các biểu thức lambda.

Biểu thức Lambda phức tạp hơn một chút vì lớp thời gian chạy được tạo ra không phải là lớp xác định nó, nhưng lớp xác định của chúng là lớp giữ mã của phần tử lambda. được gọi để xác nhận hợp lệ và khởi tạo lại cá thể lambda.

Xem SerializedLambda:

implementors lambdas serializable, chẳng hạn như các trình biên dịch hoặc các thư viện thời gian chạy ngôn ngữ, được kỳ vọng sẽ đảm bảo rằng trường hợp deserialize đúng cách. Một phương tiện để làm như vậy là đảm bảo rằng phương thức writeReplace trả về một thể hiện của SerializedLambda, thay vì cho phép tuần tự hóa mặc định để tiếp tục.

SerializedLambda có phương thức readResolve tìm phương thức tĩnh (có thể riêng tư) được gọi là $deserializeLambda$(SerializedLambda) trong lớp chụp, gọi chính nó làm đối số đầu tiên và trả về kết quả. Các lớp lambda thực hiện $deserializeLambda$ có trách nhiệm xác nhận rằng các thuộc tính của SerializedLambda nhất quán với một lambda thực sự bị lớp đó bắt giữ.

Vì vậy, ngay cả khi dụ bạn đã không được đề cập đến một phương pháp tổng hợp bên trong lớp xác định (ví dụ như trong trường hợp của một tài liệu tham khảo phương pháp để một phương pháp bên ngoài lớp này), deserialization vẫn đòi hỏi sự $deserializeLambda$ để phê chuẩn đúng đắn của các ví dụ, cố ý.


Về “thực hành tốt” của serializing lambdas, hãy ghi nhớ rằng biểu thức lambda đóng gói hành vi, không nhà nước. Lưu trữ hành vi luôn ngụ ý chỉ lưu trữ một số loại tham chiếu và yêu cầu mã nhằm phục hồi nó, để thực hiện hành vi liên quan. Điều đó cũng sẽ hoạt động nếu bạn chỉ đề cập đến hành vi dự định theo tên tượng trưng hoặc chỉ được lưu trữ, ví dụ: có liên quan enum giá trị.

Tìm hiểu thêm về ý nghĩa của việc có lambda được tuần tự hóa được giải thích trong this question.

+0

Cách "lưu trữ" tiêu chuẩn nào có thể lưu trữ các chương trình con độc lập của tiểu bang, nếu có, thay vì làm những gì tôi đang làm? –

+1

Không có cách tiêu chuẩn như bình thường bạn sẽ không lưu trữ các thường trình nhưng dữ liệu. Nếu bạn muốn lưu trữ hành vi, bạn phải hoặc là, làm cho lớp xác định có sẵn trên trang khôi phục hoặc mã thực sự lưu trữ, hoặc là mã byte hoặc như biểu thức 'Chuỗi' phải được phân tích cú pháp. – Holger

+0

Cách nào ít thực hành không tốt? Ngoài ra, đối với bất kỳ cách nào là cách tốt hơn để đi, làm cách nào để phân tích cú pháp câu lệnh/biểu thức Java khi chạy hoặc lưu trữ bytecode thẳng lên? Tôi cảm thấy như thể đây không phải là thực hành tốt, nhưng chỉ muốn tìm hiểu cách chuyển các hướng dẫn cụ thể cho Java từ chương trình sang chương trình, quy trình để xử lý. –

4

Khi bạn deserialize một đối tượng, mã làm deserialization phải biết về các lớp của đối tượng serialized. Bạn không thể tuần tự hóa một lambda tùy ý và deserialize nó trong codebase khác.

Nhiều hoặc ít hơn, mã tuần tự hóa và deserializing phải trong cùng một codebase, hoặc ít nhất phải chia sẻ một sự phụ thuộc vào mã có chứa lambda gốc.

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