जावा में 'SAM प्रकार' क्या है?


133

जावा -8 कल्पना पर पढ़ना, मैं 'एसएएम प्रकार' के संदर्भ देखता हूं। मैं इस बारे में स्पष्ट स्पष्टीकरण नहीं दे पाया हूं कि यह क्या है।

एसएएम प्रकार क्या है और किसी के उपयोग किए जाने पर इसका उदाहरण परिदृश्य क्या है?


4
Cr.openjdk.java.net/~briangoetz/lambda/lambda-state-3.html देखें (जो मुझे एक खोज के बाद मिला, जो मुझे एक और SO प्रश्न में ले गया)।
जॉन स्कीट

2
कृपया लोगों को आउट-ऑफ़-डेट जानकारी न दें। थोड़ी लंबी खोज आपको और अधिक अद्यतित संस्करण में ले गई होगी: cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html , जो स्वयं 18 महीने का है और अब कई में पुराना है स्थानों। ओपी के प्रश्न का उत्तर lambdafaq.org/what-is-a-functional-interface पर दिया गया है , जो अक्सर पूछे जाने वाले प्रश्न में एक पृष्ठ है जो मैं हाल ही में एक तेजी से बदलती भाषा और एपीआई विकास तक बना रहा।
मौरिस नेफ्तालिन

1
@MauriceNaftalin आप केवल जावा ट्रेल को लिंक कर सकते हैं , जिसे विकास टीम द्वारा अद्यतित रखा गया है।
ब्रायन

1
वर्तमान शब्द "कार्यात्मक इंटरफ़ेस" है।
newacct

1
@MauriceNaftalin: क्षमा करें, वह चूक गया। अगर मुझे लगता है कि यह निश्चित रूप से जुड़ा होता।
जॉन स्कीट

जवाबों:


142

संक्षेप में लिंक जॉन तैनात 1 मामले में यह कभी नीचे चला जाता है, "सैम" "एक सार विधि" के लिए खड़ा है, और "सैम-प्रकार" की तरह इंटरफेस को संदर्भित करता है Runnable, Callableआदि लैम्ब्डा भाव, जावा 8 में एक नई सुविधा, कर रहे हैं एक एसएएम प्रकार माना जाता है और उन्हें स्वतंत्र रूप से परिवर्तित किया जा सकता है।

उदाहरण के लिए, इस तरह के एक इंटरफेस के साथ:

public interface Callable<T> {
    public T call();
}

आप Callableइस तरह से एक लंबोदर भावों की घोषणा कर सकते हैं :

Callable<String> strCallable = () -> "Hello world!";
System.out.println(strCallable.call()); // prints "Hello world!"

इस संदर्भ में लैम्ब्डा अभिव्यक्तियाँ ज्यादातर सिंटैक्टिक शुगर हैं। वे अनाम कक्षाओं की तुलना में कोड में बेहतर दिखते हैं और विधि के नामकरण पर कम प्रतिबंधात्मक हैं। इस उदाहरण को लिंक से लें:

class Person { 
    private final String name;
    private final int age;

    public static int compareByAge(Person a, Person b) { ... }

    public static int compareByName(Person a, Person b) { ... }
}

Person[] people = ...
Arrays.sort(people, Person::compareByAge);

यह Comparatorएक विशिष्ट विधि का उपयोग करता है जो समान नाम को साझा नहीं करता है Comparator.compare, इस तरह से आपको तरीकों के नामकरण का पालन करने की आवश्यकता नहीं है और आप एक कक्षा में कई तुलना ओवरराइड कर सकते हैं, फिर मक्खी के माध्यम से तुलना करें लंबोदर भाव।

गहरा जा रहा है ...

एक गहरे स्तर पर, जावा invokedynamic7 में जोड़े गए बाइटकोड निर्देश का उपयोग करके जावा इनको लागू करता है। मैंने पहले कहा था कि लैम्बडा की घोषणा करने से अनाम वर्ग के समान Callableया उससे एक उदाहरण बनता है Comparable, लेकिन यह कड़ाई से सच नहीं है। इसके बजाय, पहली बार invokedynamicकहा जाता है, यह LambdaMetafactory.metafactoryविधि का उपयोग करके एक लैम्ब्डा फ़ंक्शन हैंडलर बनाता है , फिर लैम्ब्डा के भविष्य के आक्रमणों में इस कैश्ड उदाहरण का उपयोग करता है। इस उत्तर में अधिक जानकारी पाई जा सकती है ।

यह दृष्टिकोण जटिल है और यहां तक ​​कि कोड भी शामिल है जो आपके लैम्बडा कोड में पारित होने के लिए स्टैक मेमोरी से सीधे आदिम मूल्यों और संदर्भों को पढ़ सकता है (जैसे कि Object[]अपने लैम्ब्डा को आह्वान करने के लिए एक सरणी आवंटित करने की आवश्यकता है), लेकिन यह लैम्ब्डा कार्यान्वयन के भविष्य के पुनरावृत्तियों की अनुमति देता है। पुराने कार्यान्वयन को बदलने के लिए बिना बायोटेक अनुकूलता के बारे में चिंता किए बिना। यदि ओरेकल के इंजीनियर जेवीएम के एक नए संस्करण में अंतर्निहित लैम्ब्डा कार्यान्वयन को बदलते हैं, तो पुराने जेवीएम पर संकलित लैम्ब्डा स्वचालित रूप से डेवलपर के हिस्से पर बिना किसी बदलाव के नए कार्यान्वयन का उपयोग करेगा।


1 लिंक पर वाक्य रचना पुराना है। वर्तमान सिंटैक्स को देखने के लिए लैम्ब्डा एक्सप्रेशंस जावा ट्रेल पर एक नज़र डालें ।

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