दिलचस्प पोस्ट
बिग एंडियन के लिए लिटिल एंडियन कन्वर्ट एंड्रॉइड सिंटेक्स हाइलाइटिंग? जावा में नियमित अभिव्यक्ति के लिए टेक्स्ट से कैसे बचें एमपी 3 अवधि पाने के लिए PHP फ़ंक्शन मैं नए PostgreSQL JSON डेटाटाइप के अंदर फ़ील्ड कैसे संशोधित करूं? <a> टैग के भीतर कौन से तत्व शामिल हो सकते हैं? IntelliJ IDEA में मैं एक लाइब्रेरी (एंड्रॉइड-समर्थन- v7-appcompat) कैसे जोड़ूं? पायथन / मेटप्लोलिब – क्या असंतत अक्ष बनाने का कोई तरीका है? उपयोग और आवश्यकता के बीच अंतर मैं Python में एक datetime ऑब्जेक्ट के साथ समयक्षेत्र का उपयोग कैसे करूं? गुणा 2 संख्या और उसके बाद राशि jQuery या चयनकर्ता? श्रेणी के बाहर VBA सबस्क्रिप्ट – त्रुटि 9 आर: पनपे: एक गतिशील ईकॉमर्स पेज को स्क्रैप करना कैसे SQLite डेटाबेस में छवि को स्टोर करने के लिए

पैरामीटर के रूप में जावा पास विधि

संदर्भ द्वारा मैं एक विधि पास करने का एक तरीका तलाश रहा हूं I मैं समझता हूं कि जावा मापदंडों के रूप में तरीकों को पारित नहीं करता है, हालांकि, मैं वैकल्पिक विकल्प प्राप्त करना चाहता हूं

मुझे बताया गया है कि अंतरफलक मापदंडों के रूप में तरीकों को पार करने का विकल्प हैं, लेकिन मुझे नहीं पता कि एक इंटरफ़ेस संदर्भ द्वारा विधि के रूप में कैसे कार्य कर सकता है। अगर मैं सही ढंग से समझता हूं तो एक इंटरफ़ेस केवल उन तरीकों का सार है जो परिभाषित नहीं हैं। मैं एक इंटरफ़ेस नहीं भेजना चाहता हूं, जिसे हर बार परिभाषित करने की आवश्यकता होती है क्योंकि कई अलग-अलग विधियां उसी पैरामीटर के साथ समान विधि को कह सकती हैं।

मैं क्या पूरा करना चाहूंगा इस तरह से कुछ ऐसा है:

public void setAllComponents(Component[] myComponentArray, Method myMethod) { for (Component leaf : myComponentArray) { if (leaf instanceof Container) { //recursive call if Container Container node = (Container) leaf; setAllComponents(node.getComponents(), myMethod); } //end if node myMethod(leaf); } //end looping through components } 

जैसे लागू होते हैं:

 setAllComponents(this.getComponents(), changeColor()); setAllComponents(this.getComponents(), changeSize()); 

Solutions Collecting From Web of "पैरामीटर के रूप में जावा पास विधि"

संपादित करें : जावा 8 के रूप में, लैम्ब्डा भाव एक अच्छा समाधान है क्योंकि अन्य उत्तरों ने बताया है। नीचे जवाब जावा 7 और पहले के लिए लिखा गया था …


कमांड पैटर्न पर एक नज़र डालें

 // NOTE: code not tested, but I believe this is valid java... public class CommandExample { public interface Command { public void execute(Object data); } public class PrintCommand implements Command { public void execute(Object data) { System.out.println(data.toString()); } } public static void callCommand(Command command, Object data) { command.execute(data); } public static void main(String... args) { callCommand(new PrintCommand(), "hello world"); } } 

संपादित करें: पीट Kirkham बताते हैं , एक आगंतुक का उपयोग कर ऐसा करने का एक और तरीका है। विज़िटर का दृष्टिकोण थोड़ा अधिक सम्मिलित है – आपके नोड्स को acceptVisitor() पद्धति से विज़िटर-जागरूक होने की आवश्यकता है – लेकिन अगर आपको अधिक जटिल ऑब्जेक्ट ग्राफ़ का सामना करना पड़ता है तो इसकी जांच करना महत्वपूर्ण है।

जावा 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) 

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


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

 interface I { public void myMethod(Component component); } class A { public void changeColor(Component component) { // code here } public void changeSize(Component component) { // code here } } class B { public void setAllComponents(Component[] myComponentArray, I myMethodsInterface) { for(Component leaf : myComponentArray) { if(leaf instanceof Container) { // recursive call if Container Container node = (Container)leaf; setAllComponents(node.getComponents(), myMethodInterface); } // end if node myMethodsInterface.myMethod(leaf); } // end looping through components } } class C { A a = new A(); B b = new B(); public C() { b.setAllComponents(this.getComponents(), component -> a.changeColor(component)); b.setAllComponents(this.getComponents(), component -> a.changeSize(component)); } } 

java.lang.reflect.Method ऑब्जेक्ट और कॉल java.lang.reflect.Method उपयोग करें

सबसे पहले एक अंतरफलक को उस विधि के साथ परिभाषित करें जिसे आप पैरामीटर के रूप में देना चाहते हैं

 public interface Callable { public void call(int param); } 

विधि के साथ एक वर्ग को लागू करें

 class Test implements Callable { public void call(int param) { System.out.println( param ); } } 

// इस तरह से जोड़ना

 Callable cmd = new Test(); 

यह आपको पैरामीटर के रूप में सीएमडी पास करने देता है और इंटरफ़ेस में परिभाषित विधि कॉल को लागू करता है

 public invoke( Callable callable ) { callable.call( 5 ); } 

हालांकि यह अभी तक जावा 7 और नीचे के लिए मान्य नहीं है, मुझे विश्वास है कि हमें भविष्य को देखना चाहिए और कम से कम नए संस्करणों जैसे जावा 8 में आने वाले परिवर्तनों को पहचानना चाहिए।

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

दोनों जायके (लैम्ब्डा और विधि संदर्भ) को एक ही पद्धति के साथ एक इंटरफ़ेस की आवश्यकता होती है जिसका हस्ताक्षर उपयोग किया जाता है:

 public interface NewVersionTest{ String returnAString(Object oIn, String str); } 

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

 public static void printOutput(NewVersionTest t, Object o, String s){ System.out.println(t.returnAString(o, s)); } 

लैम्ब्डा 1 पारित होने तक यह सिर्फ एक सरल इंटरफ़ेस अभिवादन है,

 public static void main(String[] args){ printOutput( (Object oIn, String sIn) -> { System.out.println("Lambda reached!"); return "lambda return"; } ); } 

यह आउटपुट होगा:

 Lambda reached! lambda return 

विधि संदर्भ समान हैं। दिया हुआ:

 public class HelperClass{ public static String testOtherSig(Object o, String s){ return "real static method"; } } 

और मुख्य:

 public static void main(String[] args){ printOutput(HelperClass::testOtherSig); } 

उत्पादन real static method होगा विधि संदर्भ स्थिर, उदाहरण, मनमाना उदाहरणों के साथ गैर-स्थिर, और यहां तक ​​कि कंस्ट्रक्टर भी हो सकते हैं । कंस्ट्रक्टर के लिए ClassName::new जैसा कुछ ClassName::new प्रयोग किया जाएगा।

1 यह कुछ द्वारा लैम्ब्डा नहीं माना जाता है, क्योंकि इसके दुष्प्रभाव हैं। यह वर्णन करता है, हालांकि, एक अधिक सीधा-से-दृश्य दृश्य फैशन में इसका इस्तेमाल किया जाता है।

पिछली बार मैंने जांच की, जावा अपेक्षाकृत करने में सक्षम नहीं है जो आप चाहते हैं; इस तरह की सीमाओं को पाने के लिए आपको 'काम के आसपास' का उपयोग करना होगा जहां तक ​​मैं इसे देखता हूं, इंटरफेस एक विकल्प है, लेकिन एक अच्छा विकल्प नहीं है शायद जो भी आपको बताता है कि इस तरह से कुछ अर्थ था:

 public interface ComponentMethod { public abstract void PerfromMethod(Container c); } public class ChangeColor implements ComponentMethod { @Override public void PerfromMethod(Container c) { // do color change stuff } } public class ChangeSize implements ComponentMethod { @Override public void PerfromMethod(Container c) { // do color change stuff } } public void setAllComponents(Component[] myComponentArray, ComponentMethod myMethod) { for (Component leaf : myComponentArray) { if (leaf instanceof Container) { //recursive call if Container Container node = (Container) leaf; setAllComponents(node.getComponents(), myMethod); } //end if node myMethod.PerfromMethod(leaf); } //end looping through components } 

जिसे आप इसके साथ जोड़ते हैं:

 setAllComponents(this.getComponents(), new ChangeColor()); setAllComponents(this.getComponents(), new ChangeSize()); 

यदि आपको कुछ वापस करने के लिए इन विधियों की ज़रूरत नहीं है, तो आप उन्हें रननबल ऑब्जेक्ट्स वापस लौटा सकते हैं।

 private Runnable methodName (final int arg){ return new Runnable(){ public void run(){ // do stuff with arg } } } 

फिर इसे पसंद करें:

 private void otherMethodName (Runnable arg){ arg.run(); } 

ऑब्जर्वर पैटर्न का उपयोग करें (कभी-कभी लिस्टर पैटर्न भी कहा जाता है):

 interface ComponentDelegate { void doSomething(Component component); } public void setAllComponents(Component[] myComponentArray, ComponentDelegate delegate) { // ... delegate.doSomething(leaf); } setAllComponents(this.getComponents(), new ComponentDelegate() { void doSomething(Component component) { changeColor(component); // or do directly what you want } }); 

new ComponentDelegate()... इंटरफ़ेस को कार्यान्वित करने वाले एक अज्ञात प्रकार की घोषणा करता है।

जावा में नाम पास करने के लिए एक तंत्र है और इसे कॉल करें। यह प्रतिबिंब तंत्र का हिस्सा है आपके फ़ंक्शन को कक्षा विधि का अतिरिक्त पैरामीटर लेना चाहिए।

 public void YouMethod(..... Method methodToCall, Object objWithAllMethodsToBeCalled) { ... Object retobj = methodToCall.invoke(objWithAllMethodsToBeCalled, arglist); ... } 

यहां एक बुनियादी उदाहरण दिया गया है:

 public class TestMethodPassing { private static void println() { System.out.println("Do println"); } private static void print() { System.out.print("Do print"); } private static void performTask(BasicFunctionalInterface functionalInterface) { functionalInterface.performTask(); } @FunctionalInterface interface BasicFunctionalInterface { void performTask(); } public static void main(String[] arguments) { performTask(TestMethodPassing::println); performTask(TestMethodPassing::print); } } 

आउटपुट:

 Do println Do print 

मैं एक जावा विशेषज्ञ नहीं हूँ, लेकिन मैं इस तरह आपकी समस्या का समाधान करता हूं:

 @FunctionalInterface public interface AutoCompleteCallable<T> { String call(T model) throws Exception; } 

मैं अपने विशेष इंटरफेस में पैरामीटर को परिभाषित करता हूं

 public <T> void initialize(List<T> entries, AutoCompleteCallable getSearchText) {....... //call here String value = getSearchText.call(item); ... } 

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

 initialize(getMessageContactModelList(), new AutoCompleteCallable() { @Override public String call(Object model) throws Exception { return "custom string" + ((xxxModel)model.getTitle()); } }) 

जावा 8 के बाद से एक Function<T, R> इंटरफ़ेस ( डॉक्स ), जिसकी विधि है

 R apply(T t); 

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

आपके उदाहरण में आपको किसी फ़ंक्शन को पास करना होगा जो Component प्रकार को इनपुट के रूप में लेता है और कुछ भी नहीं रिटर्न – Void । इस मामले में Function<T, R> सबसे अच्छा विकल्प नहीं है, क्योंकि शून्य प्रकार का कोई autoboxing नहीं है। जिस इंटरफ़ेस को आप खोज रहे हैं उसे Consumer<T> ( डॉक्स ) विधि के साथ कहा जाता है

 void accept(T t); 

यह ऐसा दिखेगा:

 public void setAllComponents(Component[] myComponentArray, Consumer<Component> myMethod) { for (Component leaf : myComponentArray) { if (leaf instanceof Container) { Container node = (Container) leaf; setAllComponents(node.getComponents(), myMethod); } myMethod.accept(leaf); } } 

और आप इसे विधि संदर्भों का उपयोग कर कॉल करेंगे:

 setAllComponents(this.getComponents(), this::changeColor); setAllComponents(this.getComponents(), this::changeSize); 

यह मानते हुए कि आपने परिवर्तन को परिभाषित किया है colour () और changeSize () तरीकों को उसी वर्ग में।


यदि आपकी विधि एक से अधिक पैरामीटर को स्वीकार करती है, तो आप BiFunction<T, U, R> – टी और यू के इनपुट पैरामीटर के प्रकार और आर वापस होने वाले प्रकार का उपयोग कर सकते हैं। वहाँ भी BiConsumer<T, U> (दो तर्क, कोई वापसी प्रकार नहीं है)। दुर्भाग्य से 3 और अधिक इनपुट पैरामीटर के लिए, आपको अपने द्वारा इंटरफ़ेस बनाना होगा उदाहरण के लिए:

 public interface Function4<A, B, C, D, R> { R apply(A a, B b, C c, D d); }