जावा वैकल्पिक पैरामीटर


812

मैं जावा में वैकल्पिक मापदंडों का उपयोग कैसे करूं? क्या विनिर्देश वैकल्पिक मापदंडों का समर्थन करता है?

जवाबों:


516

varargs ऐसा कर सकता है (एक तरह से)। इसके अलावा, विधि की घोषणा में सभी चर आपूर्ति की जानी चाहिए। यदि आप एक चर को वैकल्पिक बनाना चाहते हैं, तो आप हस्ताक्षर का उपयोग करके विधि को अधिभारित कर सकते हैं जिसके लिए पैरामीटर की आवश्यकता नहीं है।

private boolean defaultOptionalFlagValue = true;

public void doSomething(boolean optionalFlag) {
    ...
}

public void doSomething() {
    doSomething(defaultOptionalFlagValue);
}

मेरे विचार में मेथड ओवरलोडिंग एक अच्छा जवाब है, जबकि वेरगेज बहुत खराब उत्तर है। कृपया या तो वार्गर्स पर टिप्पणी को हटा दें या एक से अधिक रिटर्न वैल्यू की संभावना के कारण होने वाले गंभीर नुकसान की व्याख्या करें।
एंड्रियास वोगल

वैश्विक चर जोड़ने से कुछ अन्य समस्याएं हो सकती हैं।
हेलेन कुई

1652

जावा में वैकल्पिक मापदंडों को अनुकरण करने के कई तरीके हैं:

  1. विधि अधिभार।

    void foo(String a, Integer b) {
        //...
    }
    
    void foo(String a) {
        foo(a, 0); // here, 0 is a default value for b
    }
    
    foo("a", 2);
    foo("a");

    इस दृष्टिकोण की सीमाओं में से एक यह है कि यह काम नहीं करता है यदि आपके पास एक ही प्रकार के दो वैकल्पिक पैरामीटर हैं और उनमें से किसी को भी छोड़ा जा सकता है।

  2. Varargs।

    क) सभी वैकल्पिक पैरामीटर एक ही प्रकार के हैं:

    void foo(String a, Integer... b) {
        Integer b1 = b.length > 0 ? b[0] : 0;
        Integer b2 = b.length > 1 ? b[1] : 0;
        //...
    }
    
    foo("a");
    foo("a", 1, 2);

    बी) वैकल्पिक मापदंडों के प्रकार भिन्न हो सकते हैं:

    void foo(String a, Object... b) {
        Integer b1 = 0;
        String b2 = "";
        if (b.length > 0) {
          if (!(b[0] instanceof Integer)) { 
              throw new IllegalArgumentException("...");
          }
          b1 = (Integer)b[0];
        }
        if (b.length > 1) {
            if (!(b[1] instanceof String)) { 
                throw new IllegalArgumentException("...");
            }
            b2 = (String)b[1];
            //...
        }
        //...
    }
    
    foo("a");
    foo("a", 1);
    foo("a", 1, "b2");

    इस दृष्टिकोण का मुख्य दोष यह है कि यदि वैकल्पिक पैरामीटर विभिन्न प्रकार के हैं तो आप स्थैतिक प्रकार की जाँच खो देते हैं। इसके अलावा, यदि प्रत्येक पैरामीटर के अलग-अलग अर्थ हैं, तो आपको उन्हें अलग करने के लिए किसी तरह की आवश्यकता है।

  3. Nulls। पिछले दृष्टिकोणों की सीमाओं को संबोधित करने के लिए आप शून्य मानों की अनुमति दे सकते हैं और फिर विधि बॉडी में प्रत्येक पैरामीटर का विश्लेषण कर सकते हैं:

    void foo(String a, Integer b, Integer c) {
        b = b != null ? b : 0;
        c = c != null ? c : 0;
        //...
    }
    
    foo("a", null, 2);

    अब सभी तर्क मूल्यों को प्रदान किया जाना चाहिए, लेकिन डिफ़ॉल्ट वाले अशक्त हो सकते हैं।

  4. वैकल्पिक वर्ग। यह दृष्टिकोण शून्य के समान है, लेकिन डिफ़ॉल्ट मान वाले पैरामीटर के लिए जावा 8 वैकल्पिक वर्ग का उपयोग करता है:

    void foo(String a, Optional<Integer> bOpt) {
        Integer b = bOpt.isPresent() ? bOpt.get() : 0;
        //...
    }
    
    foo("a", Optional.of(2));
    foo("a", Optional.<Integer>absent());

    वैकल्पिक एक फोन करने वाले के लिए एक विधि अनुबंध को स्पष्ट करता है, हालांकि, किसी को इस तरह के हस्ताक्षर भी मिल सकते हैं।

    अपडेट: जावा 8 में क्लास java.util.Optionalआउट-ऑफ-द-बॉक्स शामिल है, इसलिए जावा 8 में इस विशेष कारण के लिए अमरूद का उपयोग करने की कोई आवश्यकता नहीं है। हालांकि विधि का नाम थोड़ा अलग है।

  5. बिल्डर पैटर्न। बिल्डर पैटर्न का उपयोग कंस्ट्रक्टरों के लिए किया जाता है और एक अलग बिल्डर वर्ग शुरू करके इसे लागू किया जाता है:

     class Foo {
         private final String a; 
         private final Integer b;
    
         Foo(String a, Integer b) {
           this.a = a;
           this.b = b;
         }
    
         //...
     }
    
     class FooBuilder {
       private String a = ""; 
       private Integer b = 0;
    
       FooBuilder setA(String a) {
         this.a = a;
         return this;
       }
    
       FooBuilder setB(Integer b) {
         this.b = b;
         return this;
       }
    
       Foo build() {
         return new Foo(a, b);
       }
     }
    
     Foo foo = new FooBuilder().setA("a").build();
  6. मैप्स। जब मापदंडों की संख्या बहुत अधिक होती है और अधिकांश डिफ़ॉल्ट मानों का आमतौर पर उपयोग किया जाता है, तो आप उनके नाम या मूल्यों के मानचित्र के रूप में विधि तर्क पारित कर सकते हैं:

    void foo(Map<String, Object> parameters) {
        String a = ""; 
        Integer b = 0;
        if (parameters.containsKey("a")) { 
            if (!(parameters.get("a") instanceof Integer)) { 
                throw new IllegalArgumentException("...");
            }
            a = (Integer)parameters.get("a");
        }
        if (parameters.containsKey("b")) { 
            //... 
        }
        //...
    }
    
    foo(ImmutableMap.<String, Object>of(
        "a", "a",
        "b", 2, 
        "d", "value")); 

    जावा 9 में, यह दृष्टिकोण आसान हो गया:

        @SuppressWarnings("unchecked")
        static <T> T getParm(Map<String, Object> map, String key, T defaultValue)
        {
            return (map.containsKey(key)) ? (T) map.get(key) : defaultValue;
        }
    
        void foo(Map<String, Object> parameters) {
            String a = getParm(parameters, "a", "");
            int b = getParm(parameters, "b", 0);
            // d = ...
        }
    
        foo(Map.of("a","a",  "b",2,  "d","value"));

कृपया ध्यान दें कि आप वांछनीय परिणाम प्राप्त करने के लिए इनमें से किसी भी दृष्टिकोण को जोड़ सकते हैं।


2
@Vitalii फेडोरेंको हम्म, मुझे लगता है कि आपने # 6 में थोड़ी सी कॉपी-पेस्ट-गलती की है: आप एक इंटेगर के लिए टाइप-चेक कर रहे हैं, हालांकि आपका aवेरिएबल एक स्ट्रिंग है (कास्ट सही है)।
अज्ञात आईडी

5
@ आपकी लिंक मृत है।
रोबिनो

2
@ रोबिन वैकल्पिक लिंक यह तर्क देते हुए कि वैकल्पिक को यहाँ पैरामीटर के रूप में उपयोग नहीं किया जाना चाहिए । Optionalविकल्पों में से एक में पैरामीटर के उपयोग के बावजूद , यह उत्तर बहुत अच्छा है।
धरिक

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

1
यह शायद सबसे अच्छा जवाब होना चाहिए - सभी कवर
xproph

104

जावा 5.0 के साथ वैकल्पिक पैरामीटर है। बस अपने कार्य को इस तरह घोषित करें:

public void doSomething(boolean... optionalFlag) {
    //default to "false"
    //boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}

आप अभी doSomething();या इसके साथ कॉल कर सकते doSomething(true);हैं।


13
यह वास्तव में सही उत्तर है। यह सरल और कॉम्पैक्ट है। बस याद रखें कि आप एक से अधिक पैरामीटर प्राप्त कर सकते हैं, इसलिए जावा उन्हें एक सरणी के अंदर रखता है। उदाहरण के लिए, किसी एकल पैरामीटर को पुनः प्राप्त करने के लिए आप पहले ऐरे की सामग्री की जाँच करेंगे: 'कोड' बूलियन फ्लैग = (ऑप्शनलफ्लैग.लिफ्ट <1); गलत: ऑप्शनलफ्लैग [0];
साल्वाडोर वालेंसिया

46
नहीं, यह सही उत्तर नहीं है, क्योंकि यह एक एकल वैकल्पिक पैरामीटर की अनुमति नहीं देता है, लेकिन किसी भी वैकल्पिक पैरामीटर की संख्या। जबकि यह ओपी चाहता है के करीब है, यह समान नहीं है। यह बग और गलतफहमी का एक संभावित स्रोत है जो आपको आवश्यकता से अधिक मापदंडों को स्वीकार करने के लिए है।
सालेस्के

2
यह तरीका काम करता है यदि आपके पास बस एक वैकल्पिक पैरामीटर है, लेकिन आपको सरणी की लंबाई आदि की जांच करने की आवश्यकता होगी, तो यह सुपर साफ नहीं है: | यदि आप "एक पैरामीटर" वैकल्पिक पैरामीटर चाहते हैं, तो आप सिर्फ दो तरीकों की घोषणा कर सकते हैं (एक doSomething() { doSomething(true); }से निपटने के लिए कोई अतिभारित नहीं, कोई अस्पष्टता नहीं
rogerdpack 21

यदि कई वैकल्पिक पैरामीटर हैं, तो यह केवल तभी काम करता है जब वे सभी समान डेटा प्रकार के हों। ठीक है, आप प्रकार वस्तु बना सकते हैं, लेकिन यह वास्तव में बदसूरत हो रही है।
जय

जैसा कि @sleske ने उल्लेख किया है, varargs का उपयोग करने से एक से अधिक मूल्य पारित करने की अनुमति देने का भयानक नुकसान होता है । ओपी ने स्पष्ट रूप से "वैकल्पिक" के लिए एक समाधान के बारे में पूछा, जिसका अर्थ है या तो एक मूल्य या शून्य। यह कैसे एक अच्छा जवाब माना जा सकता है कुछ मेरे द्वारा है।
एंड्रियास वोगल

99

आप कुछ इस तरह का उपयोग कर सकते हैं:

public void addError(String path, String key, Object... params) { 
}

paramsचर वैकल्पिक है। इसे वस्तुओं की एक अशक्त सारणी के रूप में माना जाता है।

अजीब बात है, मैं इस बारे में कुछ भी दस्तावेज में नहीं मिल सका, लेकिन यह काम करता है!

यह जावा 1.5 और उसके बाद का "नया" है (जावा 1.4 या उससे पहले समर्थित नहीं है)।

मैं देखता हूं कि उपयोगकर्ता ने इसका उल्लेख नीचे किया है।


55

दुर्भाग्य से जावा सीधे डिफ़ॉल्ट मापदंडों का समर्थन नहीं करता है।

हालाँकि, मैंने जावाबीन एनोटेशन का एक सेट लिखा है, और उनमें से एक निम्नलिखित की तरह डिफ़ॉल्ट मापदंडों का समर्थन करता है:

protected void process(
        Processor processor,
        String item,
        @Default("Processor.Size.LARGE") Size size,
        @Default("red") String color,
        @Default("1") int quantity) {
    processor.process(item, size, color, quantity);
}
public void report(@Default("Hello") String message) {
    System.out.println("Message: " + message);
}

एनोटेशन प्रोसेसर इसे ठीक से समर्थन करने के लिए विधि अधिभार उत्पन्न करता है।

Http://code.google.com/p/javadude/wiki/Annotations देखें

Http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExample पर पूरा उदाहरण


53

जावा में कोई वैकल्पिक पैरामीटर नहीं हैं। आप जो कर सकते हैं वह फ़ंक्शन को ओवरलोड करना और फिर डिफ़ॉल्ट मानों को पारित करना है।

void SomeMethod(int age, String name) {
    //
}

// Overload
void SomeMethod(int age) {
    SomeMethod(age, "John Doe");
}

23

VarArgs और ओवरलोडिंग का उल्लेख किया गया है। एक अन्य विकल्प एक बिल्डर पैटर्न है, जो कुछ इस तरह दिखाई देगा:

 MyObject my = new MyObjectBuilder().setParam1(value)
                                 .setParam3(otherValue)
                                 .setParam6(thirdValue)
                                 .build();

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


मैं उस के लिए पैरामीटर निर्भरता जोड़ना चाहता हूं। आइए मैं कहता हूं कि सेट परम 3 तभी होगा जब मैं पैराम 1 सेट करूं। उदाहरण के लिए। मैं प्रगति संदेश सेट करना चाहता हूं केवल अगर मैं प्रगति दृश्यमान सेट करता हूं। isProgressVoice ()। setProgressMessage ("लोडिंग")। मैं उसे कैसे प्राप्त कर सकता हूं ?
हर्षल भट्ट

14

JDK> 1.5 में आप इसे इस तरह से उपयोग कर सकते हैं;

public class NewClass1 {

    public static void main(String[] args) {

        try {
            someMethod(18); // Age : 18
            someMethod(18, "John Doe"); // Age & Name : 18 & John Doe
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static void someMethod(int age, String... names) {

        if (names.length > 0) {
            if (names[0] != null) {
                System.out.println("Age & Name : " + age + " & " + names[0]);
            }
        } else {
            System.out.println("Age : " + age);
        }
    }
}

7

आप इस तरह से ओवरलोडिंग विधि का उपयोग करके काम कर सकते हैं।

 public void load(String name){ }

 public void load(String name,int age){}

इसके अलावा, आप @Nullable एनोटेशन का उपयोग कर सकते हैं

public void load(@Nullable String name,int age){}

बस पहले पैरामीटर के रूप में शून्य पास करें।

यदि आप एक ही प्रकार के चर से गुजर रहे हैं तो आप इसका उपयोग कर सकते हैं

public void load(String name...){}

7

लघु संस्करण :

तीन डॉट्स का उपयोग करना :

public void foo(Object... x) {
    String first    =  x.length > 0 ? (String)x[0]  : "Hello";
    int duration    =  x.length > 1 ? Integer.parseInt((String) x[1])     : 888;
}   
foo("Hii", ); 
foo("Hii", 146); 

(@ VitaliiFedorenko के जवाब पर आधारित)


2

ओवरलोडिंग ठीक है, लेकिन अगर बहुत सारे चर हैं जिन्हें डिफ़ॉल्ट मान की आवश्यकता है, तो आप इसके साथ समाप्त हो जाएंगे:

public void methodA(A arg1) {  }
public void methodA( B arg2,) {  }
public void methodA(C arg3) {  }
public void methodA(A arg1, B arg2) {  }
public void methodA(A arg1, C arg3) {  }
public void methodA( B arg2, C arg3) {  }
public void methodA(A arg1, B arg2, C arg3) {  }

इसलिए मैं सुझाव दूंगा कि जावा द्वारा उपलब्ध चर तर्क का उपयोग किया जाए। यहाँ स्पष्टीकरण के लिए एक लिंक है।


वर्गास का उपयोग करना बुरा व्यवहार माना जाता है। यदि सिस्टम को ऐसी (उपर्युक्त) विधियों की आवश्यकता है, तो आपको एक नए डिजाइन के बारे में सोचना चाहिए क्योंकि वर्ग डिजाइन खराब दिखता है।
डियाब्लो

2
यह जावा की कमियों का बहाना बनाने के लिए और भी बदतर अभ्यास है, और उन असुविधाओं को ध्यान देने और वर्कअराउंड को तैयार करने के लिए दूसरों पर बुरे व्यवहार का आरोप लगाते हैं।
ब्रायनो

1
कृपया बाहरी स्रोतों से लिंक करने के बजाय अपने उत्तर में सभी प्रासंगिक जानकारी जोड़ें - दिया गया लिंक मृत है
निको हेस

2

आप एक ऐसे वर्ग का उपयोग कर सकते हैं जो एक बिल्डर की तरह काम करता है ताकि आपके वैकल्पिक मान इस तरह हों।

public class Options {
    private String someString = "default value";
    private int someInt= 0;
    public Options setSomeString(String someString) {
        this.someString = someString;
        return this;
    }
    public Options setSomeInt(int someInt) {
        this.someInt = someInt;
        return this;
    }
}

public static void foo(Consumer<Options> consumer) {
    Options options = new Options();
    consumer.accept(options);
    System.out.println("someString = " + options.someString + ", someInt = " + options.someInt);
}

का उपयोग करें

foo(o -> o.setSomeString("something").setSomeInt(5));

आउटपुट है

someString = something, someInt = 5

सभी वैकल्पिक मूल्यों को छोड़ने के लिए आपको इसे पसंद करना होगा foo(o -> {});या यदि आप चाहें, तो आप एक दूसरा बना सकते हैंfoo() तरीका जो वैकल्पिक मापदंडों को नहीं लेता है।

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


1

जावा अब 1.8 में वैकल्पिक का समर्थन करता है, मैं एंड्रॉइड पर प्रोग्रामिंग के साथ फंस गया हूं, इसलिए मैं नल का उपयोग कर रहा हूं, जब तक कि मैं वैकल्पिक प्रकारों का उपयोग करने के लिए कोड को रिफ्लेक्टर नहीं कर सकता।

Object canBeNull() {
    if (blah) {
        return new Object();
    } else {
        return null;
    }
}

Object optionalObject = canBeNull();
if (optionalObject != null) {
    // new object returned
} else {
    // no new object returned
}

क्या आप कृपया उदाहरण प्रदान कर सकते हैं?
सेफ़र

1

जावा में डिफ़ॉल्ट तर्कों का उपयोग नहीं किया जा सकता है। जहाँ C #, C ++ और Python में, हम उनका उपयोग कर सकते हैं ।।

जावा में, हमें डिफ़ॉल्ट मापदंडों के साथ एक के बजाय 2 विधियों (कार्यों) का उपयोग करना होगा।

उदाहरण:

Stash(int size); 

Stash(int size, int initQuantity);

http://parvindersingh.webs.com/apps/forums/topics/show/8856498-java-how-to-set-default-parameters-values-like-c-


28
C # के नए संस्करण डिफ़ॉल्ट पैरामीटर की अनुमति देते हैं।
सोगर

2
जावा में किसी भी पैरामीटर के लिए "..." विकल्प है।
काछो सांता

0

यह एक पुराना प्रश्न है, भले ही वास्तविक वैकल्पिक प्रकार पेश किए जाने से पहले लेकिन इन दिनों आप कुछ बातों पर विचार कर सकते हैं: - विधि का उपयोग ओवरलोडिंग - वैकल्पिक प्रकार का उपयोग करें, जो वैकल्पिक प्रकार से गुजरने से बचने का लाभ जावा 8 में आमतौर पर उपयोग होने से पहले पेश किया गया था। Google के अमरूद जैसे तीसरे पक्ष के दायित्व से। वैकल्पिक के रूप में मापदंडों / तर्कों का उपयोग करना अति-उपयोग के रूप में माना जा सकता है क्योंकि मुख्य उद्देश्य इसे वापसी समय के रूप में उपयोग करना था।

Ref: https://itcodehub.blogspot.com/2019/06/using-optional-type-in-java.html


0

हम विधि अधिभार या DataType का उपयोग करके वैकल्पिक पैरामीटर बना सकते हैं ...

| * | विधि अधिभार:

RetDataType NameFnc(int NamePsgVar)
{
    // |* Code Todo *|
    return RetVar;
}

RetDataType NameFnc(String NamePsgVar)
{
    // |* Code Todo *|
    return RetVar;
}

RetDataType NameFnc(int NamePsgVar1, String NamePsgVar2)
{
    // |* Code Todo *|
    return RetVar;
}

सबसे आसान तरीका है

| * | DataType ... वैकल्पिक पैरामीटर हो सकता है

RetDataType NameFnc(int NamePsgVar, String... stringOpnPsgVar)
{
    if(stringOpnPsgVar.length == 0)  stringOpnPsgVar = DefaultValue; 

    // |* Code Todo *|
    return RetVar;
}


8
RetDtaTyp... गंभीरता से? क्या RetDataTypeटाइप करना बहुत मुश्किल है?
अलेक्जेंडर - मोनिका

क्या आप उस कोड में कुछ और स्पष्टीकरण जोड़ सकते हैं? ये सभी अजीब चर क्या करते हैं?
निको हासे

समझने में आसानी के लिए परिवर्तनशील नामों को बदल दिया ...
सुजय यूएन

0

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

public abstract class Invoker<T> {
    public T apply() {
        return apply(null);
    }
    public abstract T apply(Object... params);
}

0

यदि यह एक एपीआई समापन बिंदु है, तो एक सुंदर तरीका "स्प्रिंग" एनोटेशन का उपयोग करना है:

@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam(required = false, defaultValue = "hello") String id) { 
    return innerFunc(id);
}

इस मामले में ध्यान दें कि इनरफंक को वैरिएबल की आवश्यकता होगी, और चूंकि यह एपि समापन बिंदु नहीं है, इसलिए इसे वैकल्पिक बनाने के लिए इस स्प्रिंग एनोटेशन का उपयोग नहीं किया जा सकता है। संदर्भ: https://www.baeldung.com/spring-request-param

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