दिलचस्प पोस्ट
क्या हम जावा में अहस्ताक्षरित बाइट बना सकते हैं? जब स्क्रॉल सक्षम किया जाता है, तो `कॉल ड्रागिंग कैश 'पर कॉल करें गिट – अनट्रैक किए गए सामग्री को ट्रैक करने के लिए कैसे? बनाम क्लिक विधियों पर jquery एक निजी संशोधक के साथ, अन्य ऑब्जेक्ट्स में सदस्य सीधे प्रवेश क्यों कर सकते हैं? कुछ तत्वों के लिए असंगत अक्षम करें ईएफ कोड के लिए ProviderManifestToken को कॉन्फ़िगर कैसे करें क्यों एक अनाम नाम स्थान स्थिर "बेहतर" विकल्प है? आर में क्या%%% का क्या मतलब है? मैं दो दृश्य नियंत्रकों के बीच संवाद करने के लिए एक साधारण प्रतिनिधि कैसे स्थापित करूं? एंड्रॉइड एक कैमरे के बिटमैप की ओरिएंटेशन प्राप्त करें? और पीछे -90 डिग्री घुमाएं डेटा रीडर से डेटा टेबल को व्यवस्थित करें jQuery क्लिक कार्यक्रम से झूठी वापसी निष्पादित लेनदेन के लिए पुनरावर्ती प्रविष्टि क्या स्ट्रैक्टस इंटरफेस लागू करने के लिए यह सुरक्षित है?

जावा में पैरामीटर के रूप में फ़ंक्शन कैसे पास करें?

क्या किसी विधि को जावा पैरामीटर में पैरामीटर के रूप में पास करना संभव है? यदि हां, तो क्या कोई मुझे मार्गदर्शन कर सकता है? यह तुच्छ नहीं लगता है

Solutions Collecting From Web of "जावा में पैरामीटर के रूप में फ़ंक्शन कैसे पास करें?"

नोट : जावा 8 के बाद जावा के संस्करणों के लिए निम्नलिखित उत्तर पर्याप्त हैं। यदि आप जावा 8 का उपयोग कर रहे हैं, तो 'जावा 8 लैम्ब्डा एक्सप्रेशन' देखें मैं नीचे बताए हुए शब्दों के लिए यह वाक्य-रचनात्मक चीनी है।

एक आम पैटर्न एक इंटरफेस में 'लपेटो' के लिए होगा, जैसे कि Callable , उदाहरण के लिए, फिर आप एक कोलाबल में पास करते हैं:

 public T myMethod(Callable<T> func) { return func.call(); } 

यह पैटर्न कमांड पैटर्न के रूप में जाना जाता है

ध्यान रखें कि आप अपने विशेष उपयोग के लिए एक इंटरफ़ेस बनाना सबसे अच्छा होगा। यदि आप कोने योग्य के साथ जाने का फैसला किया है, तो आप ऊपर की जगह को ऊपर की जगह लेते हैं, जो कि आपके द्वारा अपेक्षित रिटर्न मान की तरह होता है, जैसे स्ट्रिंग।

आपकी टिप्पणी के जवाब में आप कह सकते हैं:

 public int methodToPass() { // do something } public void dansMethod(int i, Callable<Integer> myFunc) { // do something } 

तो इसे कॉल करें, शायद एक गुमनाम अंदरूनी वर्ग का उपयोग कर:

 dansMethod(100, new Callable<Integer>() { public Integer call() { return methodToPass(); } }); 

ध्यान रखें कि यह एक 'चाल' नहीं है यह फ़ंक्शन पॉइन्टर के बराबर जावा का मूल संकल्पनात्मक है।

आप ऐसा करने के लिए जावा प्रतिबिंब का उपयोग कर सकते हैं। विधि को java.lang.reflect.Method के एक उदाहरण के रूप में प्रस्तुत किया जाएगा।

 import java.lang.reflect.Method; public class Demo { public static void main(String[] args) throws Exception{ Class[] parameterTypes = new Class[1]; parameterTypes[0] = String.class; Method method1 = Demo.class.getMethod("method1", parameterTypes); Demo demo = new Demo(); demo.method2(demo, method1, "Hello World"); } public void method1(String message) { System.out.println(message); } public void method2(Object object, Method method, String message) throws Exception { Object[] parameters = new Object[1]; parameters[0] = message; method.invoke(object, parameters); } } 

लैम्ब्डा भाव

जेके के उत्कृष्ट उत्तर को जोड़ने के लिए, अब आप लैम्ब्डा एक्सप्रेशंस (जावा 8) में आसानी से एक विधि पास कर सकते हैं। सबसे पहले, कुछ पृष्ठभूमि एक कार्यात्मक इंटरफ़ेस एक इंटरफ़ेस होता है जिसमें एक और केवल एक सार विधि होती है, हालांकि इसमें किसी भी संख्या में डिफ़ॉल्ट विधियां (जावा 8 में नया) और स्थिर विधियां शामिल हो सकती हैं। लैम्ब्डा अभिव्यक्ति यदि आप लैम्ब्डा अभिव्यक्ति का उपयोग नहीं करते हैं तो सभी अनावश्यक वाक्यविन्यास के बिना, अमूर्त पद्धति को तुरंत लागू कर सकते हैं।

लैम्ब्डा अभिव्यक्तियों के बिना:

 obj.aMethod(new AFunctionalInterface() { @Override public boolean anotherMethod(int i) { return i == 982 } }); 

लैम्ब्डा अभिव्यक्तियों के साथ:

 obj.aMethod(i -> i == 982); 

यहां लैम्ब्डा एक्सप्रेशंस पर जावा ट्यूटोरियल से एक अंश है:

लम्बा अभिव्यक्ति का सिंटेक्स

लैम्ब्डा अभिव्यक्ति में निम्नलिखित शामिल हैं:

  • कोष्ठकों में संलग्न औपचारिक मापदंडों की एक अल्पविराम से पृथक सूची। CheckPerson.test विधि में एक पैरामीटर शामिल है, p, जो व्यक्ति वर्ग की एक आवृत्ति का प्रतिनिधित्व करता है।

    नोट : आप लैम्ब्डा अभिव्यक्ति में पैरामीटर के डेटा प्रकार को छोड़ सकते हैं। इसके अलावा, यदि केवल एक पैरामीटर है तो आप कोष्ठक को छोड़ सकते हैं उदाहरण के लिए, निम्न लैम्ब्डा अभिव्यक्ति भी मान्य है:

     p -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25 
  • तीर टोकन, ->

  • एक शरीर, जिसमें एक एकल अभिव्यक्ति या एक बयान ब्लॉक शामिल है। यह उदाहरण निम्न अभिव्यक्ति का उपयोग करता है:

     p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25 

    यदि आप एक एकल अभिव्यक्ति निर्दिष्ट करते हैं, तो जावा रनटाइम अभिव्यक्ति का मूल्यांकन करता है और उसके बाद उसका मान वापस आता है। वैकल्पिक रूप से, आप रिटर्न कथन का उपयोग कर सकते हैं:

     p -> { return p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25; } 

    रिटर्न स्टेटमेंट एक अभिव्यक्ति नहीं है; लैम्ब्डा अभिव्यक्ति में, आपको ब्रेसिज़ ({}) में वक्तव्य देना होगा। हालांकि, आपको ब्रेसिज़ में एक शून्य विधि आवंटन को शामिल करने की आवश्यकता नहीं है। उदाहरण के लिए, निम्नलिखित एक मान्य लैम्ब्डा अभिव्यक्ति है:

     email -> System.out.println(email) 

ध्यान दें कि लैम्ब्डा अभिव्यक्ति एक विधि घोषणा की तरह बहुत लगती है; आप लैम्ब्डा अभिव्यक्तियों को नाम के बिना अज्ञात विधियों-विधियों के रूप में मान सकते हैं।


लैम्ब्डा अभिव्यक्ति का उपयोग करके आप यहां "विधि पारित" कर सकते हैं:

नोट: यह एक नया मानक कार्यात्मक इंटरफ़ेस, java.util.function.IntConsumer का उपयोग करता है

 class A { public static void methodToPass(int i) { // do stuff } } 
 import java.util.function.IntConsumer; class B { public void dansMethod(int i, IntConsumer aMethod) { /* you can now call the passed method by saying aMethod.accept(i), and it will be the equivalent of saying A.methodToPass(i) */ } } 
 class C { B b = new B(); public C() { b.dansMethod(100, j -> A.methodToPass(j)); //Lambda Expression here } } 

उपरोक्त उदाहरण :: ऑपरेटर का उपयोग करके और भी छोटा किया जा सकता है।

 public C() { b.dansMethod(100, A::methodToPass); } 

जावा 8 को धन्यवाद, किसी फ़ंक्शन को किसी विधि में पास करने के लिए आपको नीचे दिए गए चरणों को करने की आवश्यकता नहीं है, यह वही है जो लैम्ब्डा के लिए है, ओरेकल के लेम्बा एक्सप्रेशन ट्यूटोरियल देखें । इस पोस्ट के बाकी बताते हैं कि हमने इस कार्यक्षमता को लागू करने के लिए बुरे पुराने दिनों में क्या करना था।

आमतौर पर आप एक विधि के साथ कुछ इंटरफ़ेस लेने के रूप में अपनी विधि घोषित करते हैं, फिर आप उस ऑब्जेक्ट में पास करते हैं जो इंटरफ़ेस लागू करता है। एक उदाहरण कॉमन्स-संग्रह में है, जहां आपके पास क्लोजर, ट्रांसफार्मर और प्रीडिक्ट के लिए इंटरफेस है, और उन तरीकों के लिए जिन्हें आप इनके कार्यान्वयन को पास करते हैं अमरूद के नए सुधारों में अमरूद है, आप वहां समान इंटरफेस पा सकते हैं।

इसलिए उदाहरण के लिए, कॉमन्स-संग्रह में org.apache.commons.collections.CollectionUtils है, जिसमें बहुत सारे स्थैतिक विधियां हैं जो ऑब्जेक्ट्स को पास करते हैं, एक यादृच्छिक रूप से लेने के लिए, इस हस्ताक्षर के साथ मौजूद एक नाम मौजूद है:

 static boolean exists(java.util.Collection collection, Predicate predicate) 

यह एक ऐसा उद्देश्य लेता है जो इंटरफ़ेस प्रीडिकेट लागू करता है, जिसका अर्थ है कि इसमें उस पर एक विधि होनी चाहिए जो कुछ ऑब्जेक्ट लेती है और एक बूलियन देता है।

तो मैं इसे इस तरह कह सकता हूं:

 CollectionUtils.exists(someCollection, new Predicate() { public boolean evaluate(Object object) { return ("a".equals(object.toString()); } }); 

और यह सच या झूठे देता है कि क्या कुछ someCollection में एक ऑब्जेक्ट है, जिसके लिए वास्तविक रिटर्न सच है।

वैसे भी, यह सिर्फ एक उदाहरण है, और आम-संग्रह पुराना है। मैं सिर्फ पेरू में बराबर भूल गया

जावा क्लोजर का समर्थन करता है बस ठीक है। यह फ़ंक्शंस का समर्थन नहीं करता है , इसलिए आपके पास बंद करने के लिए उपयोग की जाने वाली सिंटैक्स अधिक अजीब और भारी है: आपको किसी विधि के साथ एक कक्षा में सब कुछ लपेट कर रखना होगा। उदाहरण के लिए,

 public Runnable foo(final int x) { return new Runnable() { public void run() { System.out.println(x); } }; } 

एक रननेबल ऑब्जेक्ट वापस लौटाएगा, जिसका run() विधि में "समाप्त हो गया" x पास किया गया था, जैसे कि किसी भी भाषा में जो प्रथम श्रेणी के कार्यों और क्लोजर का समर्थन करता है।

मुझे पता है कि यह एक पुरानी पोस्ट है, लेकिन मेरे पास एक और थोड़ा सरल समाधान है। आप भीतर एक और वर्ग बना सकते हैं और इसे सार बना सकते हैं। आगे एक सार विधि नाम इसे आप जो भी पसंद करते हैं। मूल कक्षा में एक ऐसा तरीका बनाओ, जो नए वर्ग को पैरामीटर के रूप में लेता है, इस पद्धति में सार पद्धति को बुलाता है। यह ऐसा कुछ दिखाई देगा

 public class Demo { public Demo(/.../){ } public void view(Action a){ a.preform(); } /** * The Action Class is for making the Demo * View Custom Code */ public abstract class Action { public Action(/.../){ } abstract void preform(); } } 

अब आप इस तरह से ऐसा कुछ कर सकते हैं कि कक्षा में से किसी विधि को कॉल करें।

 /... Demo d = new Demo; Action a = new Action() { @Override void preform() { //Custom Method Code Goes Here } }; /.../ d.view(a) 

जैसा कि मैंने कहा मैं अपनी पुरानी जानता हूं, लेकिन इस तरह मुझे लगता है कि यह थोड़ा आसान है। आशा करता हूँ की ये काम करेगा।

मैंने कमांड पैटर्न का इस्तेमाल किया है कि @ जेक। उल्लेख किया, एक वापसी प्रकार जोड़ना:

 public interface Callable<I, O> { public O call(I input); } 

जावा (अभी तक) बंद करने का समर्थन नहीं करता लेकिन स्काला और ग्रोविइ जैसी अन्य भाषाएं हैं जो जेवीएम में चलती हैं और समर्थन बंद कर देती हैं।