लैम्बडा सीरियल कैसे करें?


157

मैं एक लंबोदर को कैसे भव्य रूप से अनुक्रमित कर सकता हूं?

उदाहरण के लिए, नीचे दिया गया कोड एक फेंकता है NotSerializableExceptionSerializableRunnable"डमी" इंटरफ़ेस बनाए बिना मैं इसे कैसे ठीक कर सकता हूं ?

public static void main(String[] args) throws Exception {
    File file = Files.createTempFile("lambda", "ser").toFile();
    try (ObjectOutput oo = new ObjectOutputStream(new FileOutputStream(file))) {
        Runnable r = () -> System.out.println("Can I be serialized?");
        oo.writeObject(r);
    }

    try (ObjectInput oi = new ObjectInputStream(new FileInputStream(file))) {
        Runnable  r = (Runnable) oi.readObject();
        r.run();
    }
}

18
हालांकि यह संभव है (चयनित उत्तर देखें), हर किसी को शायद वास्तव में ऐसा करने के बारे में दो बार सोचना चाहिए। यह आधिकारिक तौर पर "दृढ़ता से हतोत्साहित" है और इसमें गंभीर सुरक्षा निहितार्थ हो सकते हैं ।
डेविड

जवाबों:


260

जावा 8 कई सीमाएं जोड़कर किसी वस्तु को चौराहे पर डालने की संभावना का परिचय देता है । क्रमांकन के मामले में, इसलिए लिखना संभव है:

Runnable r = (Runnable & Serializable)() -> System.out.println("Serializable!");

और लैम्ब्डा ऑटोमैटिक रूप से सीरियलेबल हो जाता है।


4
बहुत दिलचस्प - यह सुविधा काफी शक्तिशाली लगती है। क्या लैंबडैसिंग के बाहर इस तरह की कास्ट एक्सप्रेशन का कोई उपयोग है? जैसे क्या अब एक साधारण अनाम वर्ग के साथ भी कुछ ऐसा करना संभव है?
बाल्दर

6
@ बेल्डर लैम्बदास के प्रकार की खोज के लिए एक लक्ष्य प्रकार प्रदान करने के लिए एक चौराहे के प्रकार को जोड़ने की सुविधा जोड़ी गई थी। चूंकि AIC में एक प्रकट प्रकार होता है (यानी, इसका प्रकार अनुमान नहीं है) AIC को किसी चौराहे के प्रकार में डालना उपयोगी नहीं है। (यह संभव है, बस उपयोगी नहीं है।) एआईसी ने कई इंटरफेस को लागू करने के लिए, आपको एक नया सबइंटरफेस तैयार करना होगा जो उन सभी को बढ़ाता है, और फिर उसे तुरंत लागू करता है।
स्टुअर्ट मार्क्स

2
क्या यह संकलक चेतावनी का उत्पादन करेगा, यह कहते हुए कि कोई सीरियलवर्जन को परिभाषित नहीं किया गया है?
किरिल रहमान

11
नोट: यह केवल तभी काम करता है जब आप निर्माण के दौरान कलाकारों को लागू करते हैं। निम्नलिखित एक ClassCastException को फेंक देगा: Runnable r = () -> System.out.println ("Serializable!"); Runnable serializableR = (Runnable & Serializable) r;
bcody

3
@bcody हाँ यह भी देखें: stackoverflow.com/questions/25391656/…
assylias

24

उसी निर्माण का उपयोग विधि संदर्भों के लिए किया जा सकता है। उदाहरण के लिए यह कोड:

import java.io.Serializable;

public class Test {
    static Object bar(String s) {
        return "make serializable";
    }

    void m () {
        SAM s1 = (SAM & Serializable) Test::bar;
        SAM s2 = (SAM & Serializable) t -> "make serializable";
    }

    interface SAM {
        Object action(String s);
    }
}

एक लंबोदर अभिव्यक्ति और एक धारावाहिक लक्ष्य प्रकार के साथ एक विधि संदर्भ को परिभाषित करता है।


18

बहुत बदसूरत डाली। मैं जिस कार्यात्मक इंटरफ़ेस का उपयोग कर रहा हूं, उसके लिए एक सीरियल विस्तारक को परिभाषित करना पसंद करता हूं

उदाहरण के लिए:

interface SerializableFunction<T,R> extends Function<T,R>, Serializable {}
interface SerializableConsumer<T> extends Consumer<T>, Serializable {}

तब मेमने को स्वीकार करने की विधि को इस प्रकार परिभाषित किया जा सकता है:

private void someFunction(SerializableFunction<String, Object> function) {
   ...
}

और आप किसी भी बदसूरत डाली के बिना अपने लंबो पास कर सकते हैं और समारोह को बुला रहे हैं:

someFunction(arg -> doXYZ(arg));

2
मुझे यह उत्तर पसंद है क्योंकि तब कोई भी बाहरी कॉलगर्ल जो आप नहीं लिखते हैं, स्वचालित रूप से भी धारावाहिक हो जाएगी। यदि आप चाहते हैं कि प्रस्तुत की जाने वाली वस्तुएँ क्रमबद्ध हों, तो आपका इंटरफ़ेस क्रमबद्ध होना चाहिए, जो एक इंटरफ़ेस के बिंदु की तरह है। हालांकि, सवाल ने कहा कि "एक SerializableRunnable'डमी' इंटरफ़ेस
बनाए

4

यदि कोई व्यक्ति बीम / डेटाफ़्लो कोड बनाते समय यहाँ गिरता है:

बीम का अपना SerializableFunction इंटरफ़ेस है, इसलिए डमी इंटरफ़ेस या वर्बोज़ कास्ट की कोई आवश्यकता नहीं है।


3

यदि आप क्रियो की तरह एक और क्रमांकन ढांचे पर स्विच करने के लिए तैयार हैं , तो आप कई सीमा या आवश्यकता से छुटकारा पा सकते हैं जो कार्यान्वित इंटरफ़ेस को लागू करना होगा Serializable। के लिए दृष्टिकोण है

  1. InnerClassLambdaMetafactoryक्रमबद्धता के लिए हमेशा आवश्यक कोड जनरेट करें
  2. सीधे LambdaMetaFactorydeserialization के दौरान कॉल करें

विवरण और कोड के लिए इस ब्लॉग पोस्ट को देखें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.