क्या जावा डिफ़ॉल्ट पैरामीटर मानों का समर्थन करता है?


1660

मैं कुछ जावा कोड के साथ आया, जिसमें निम्न संरचना थी:

public MyParameterizedFunction(String param1, int param2)
{
    this(param1, param2, false);
}

public MyParameterizedFunction(String param1, int param2, boolean param3)
{
    //use all three parameters here
}

मुझे पता है कि C ++ में मैं एक पैरामीटर को एक डिफ़ॉल्ट मान दे सकता हूं। उदाहरण के लिए:

void MyParameterizedFunction(String param1, int param2, bool param3=false);

क्या जावा इस तरह के सिंटैक्स का समर्थन करता है? क्या कोई कारण है कि यह दो कदम वाक्यविन्यास बेहतर क्यों है?


85
हालांकि, बिल्डर पैटर्न मदद कर सकता है।
डेव जार्विस

50
मैं वास्तव में इस सुविधा को याद करता हूं। किसी फ़ंक्शन या कंस्ट्रक्टर के लिए अतिरिक्त पैरामीटर लेने के लिए मौजूदा कोड को संशोधित करते समय यह बहुत मदद करता है
जतिन

4
@ जतिन एक्लिप्स "चेंज मेथड सिग्नेचर" के साथ रिफैक्टरिंग आप एक पैरामीटर जोड़ सकते हैं और एक डिफ़ॉल्ट मान प्रदान कर सकते हैं जो कि मौजूदा इनवोकरों का उपयोग करेगा।
इरविन बोलाविद्ट

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

3
@temporary_user_name public MyParameterizedFunction(String param1, int param2)एक रचनाकार है, विधि नहीं, घोषणा।
मारियो इशाक

जवाबों:


955

नहीं, जो संरचना आपको मिली है वह यह है कि जावा इसे कैसे संभालता है (जो कि डिफ़ॉल्ट मापदंडों के बजाय ओवरलोडिंग के साथ है)।

कंस्ट्रक्टरों के लिए, प्रभावी जावा देखें: यदि ओवरलोडिंग जटिल हो रही है तो भाषा गाइड के आइटम 1 टिप (कंस्ट्रक्टरों के बजाय स्थैतिक कारखाने के तरीकों पर विचार करें) प्रोग्रामिंग करें। अन्य तरीकों के लिए, कुछ मामलों का नाम बदलने या पैरामीटर ऑब्जेक्ट का उपयोग करने से मदद मिल सकती है। यह तब है जब आपके पास पर्याप्त जटिलता है कि अंतर करना मुश्किल है। एक निश्चित मामला वह है जहां आपको मापदंडों के क्रम का उपयोग करके अंतर करना है, न कि केवल संख्या और प्रकार।



135
@JarrodRoberson: स्थैतिक कारखाने के तरीकों से अधिक हानिकारक नहीं हैं new। उनका उपयोग हर समय नए कोड में किया जाता है । साधारण मूल्य की वस्तुओं के लिए बिल्डर्स अक्सर ओवर-इंजीनियरिंग का परिणाम होते हैं।
लीई

12
@JarrodRoberson: संकलक के माध्यम से सही उपयोग को मजबूर करने का दिलचस्प तरीका, साझा करने के लिए धन्यवाद! भविष्य के पदों के लिए अनुकूल सुझाव: अधूरा स्रोत कोड की 300 लाइनें शायद ज्यादातर लोगों के लिए पचाने के लिए थोड़ी सी हैं (कोड को पढ़ना मुश्किल है, लिखने के लिए, आखिरकार)। एक बार फिर धन्यवाद!
क्रिश्चियन आइचिंगर २ Christian

17
@JarrodRoberson: अच्छा है, इसके लिए तत्पर हैं! जो मैं संवाद करना चाहता था: आपके ब्लॉग के पाठक के रूप में, जो कुछ चल रहा है उसका संक्षिप्त पाठ विवरण के साथ 50 लाइन का उदाहरण मुझे बिना संदर्भ के 300 से अधिक लाइनों में मदद करेगा।
क्रिश्चियन आइचिन्जर

8
@ user177800 असहमत - स्थिर कार्य अगर शुद्ध कार्यों के रूप में लिखे गए हैं तो पूरी तरह से ठीक हैं। यह तब होता है जब एक स्थिर कार्य यह बताता है कि वे एक समस्या बन गए हैं ...
लेवी फुलर

641

नहीं, लेकिन आप बिल्डर पैटर्न का उपयोग कर सकते हैं , जैसा कि इस स्टैक ओवरफ्लो उत्तर में वर्णित है ।

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

Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
                 .name("Spicoli")
                 .age(16)
                 .motto("Aloha, Mr Hand")
                 .buildStudent();

जिसमें कुछ फ़ील्ड में डिफ़ॉल्ट मान हो सकते हैं या अन्यथा वैकल्पिक हो सकते हैं।


141
अंत में ई बहुत कम से कम 2-पेज बिल्डर पैटर्न का उदाहरण है।
नेवरमाइंड

14
Im जिज्ञासु, हालांकि, हमें बिल्डर पैटर्न का उपयोग करते समय एक बिल्डर वर्ग की आवश्यकता क्यों है। , मैं एस 1 = नए छात्र छात्र की सोच रहा था () नाम ( "Spicolo") उम्र (16) .motto ( "अलोहा, श्री
ivanceras

52
@ivanceras: यह तब प्रासंगिक है जब वर्गों के लिए आवश्यक फ़ील्ड हैं, और आप उन कक्षाओं को अमान्य स्थिति में तुरंत सक्षम नहीं करना चाहते हैं। इसलिए यदि आपने अभी कहा है Student s1 = new Student().age(16);तो वह आपको बिना नाम के एक छात्र के साथ छोड़ देगा, जो बुरा हो सकता है। यदि यह बुरा नहीं है, तो आपका समाधान ठीक है।
एली कोर्टराइट

57
@ivanceras: एक और कारण यह है कि आप चाहते हैं कि आपकी कक्षा निर्माण के बाद अपरिवर्तनीय हो सकती है, इसलिए आप इसमें ऐसे तरीके नहीं चाहते हैं जो इसके मूल्यों को बदल दें।
जूल्स

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

485

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

  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());

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

  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 = (String)parameters.get("a");
        } else if (parameters.containsKey("b")) { 
            //... 
        }
        //...
    }
    
    foo(ImmutableMap.<String, Object>of(
        "a", "a",
        "b", 2, 
        "d", "value")); 

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


1
अच्छे खर्च। मैंने कभी भी इस तरह से इस्तेमाल किए गए रिटर्न वैल्यू नहीं देखे हैं। 5 के लिए) क्या करते return thisहैं? इसके अलावा, FooBuilder().setA("a").build();तब से (परिभाषा के अनुसार) निर्माता को पहले बुलाया जाता है और FooBuilder()एक मूल्य लौटाता है, इसका मतलब .setA("a"):यह नहीं है कि उसे बुलाया जाने का मौका नहीं मिलता है?
सेलेरिटास

3
@Celeritas return thisवही ऑब्जेक्ट लौटाता है जिस पर विधि को (उदाहरण में FooBuilder) कहा जाता था । यह एक वस्तु को एक ही वस्तु पर कार्य करने के तरीकों की व्याख्या करने की अनुमति देता है: new FooBuilder().setA(..).setB(..).setC(..)आदि के रूप में एक अलग बयान में प्रत्येक विधि को कॉल करने का विरोध किया।
ADTC

2
@Celeritas new FooBuilder()एक FooBuilderऑब्जेक्ट देता है जिस पर setAविधि कहा जाता है। जैसा setBकि नहीं कहा जाता है, this.bडिफ़ॉल्ट मान को बरकरार रखता है। अंत में buildइस FooBuilderऑब्जेक्ट पर विधि को बुलाया जाता है । buildविधि बनाता है और एक रिटर्न Fooवस्तु जो चर के लिए निर्धारित है Foo foo। ध्यान दें कि FooBuilderऑब्जेक्ट किसी भी चर में संग्रहीत नहीं है।
ADTC

डिफ़ॉल्ट पैरामीटर बनाने के लिए एनोटेशन का भी उपयोग किया जा सकता है और पॉलीमॉर्फिक संग्रह के लिए आवश्यक होने पर सबसे उपयोगी है। docs.oracle.com/javase/tutorial/java/annotations/declaring.html
मार्टिन

1
दो प्रश्नों में एक ही उत्तर पर 900 से अधिक उत्थान। मैं प्रभावित हूँ: stackoverflow.com/questions/965690/java-optional-parameters/…
AdamMc331

256

दुख की बात है नहीं।


34
क्या यह इतना दुखद है? ऐसा करने से संभावित अस्पष्ट फ़ंक्शन हस्ताक्षर शुरू होंगे।
ट्रे

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

32
मैं यह देखने में विफल रहता हूं कि पैरामीटर डिफॉल्ट्स फ़ंक्शन ओवरलोडिंग को कैसे रोकते हैं। उदाहरण के लिए C # ओवरराइड की अनुमति देता है और डिफ़ॉल्ट इनिशियलाइज़ के लिए भी अनुमति देता है। मनमाना चुनाव पसंद है, प्रतिबंध नहीं इसका कारण है।
फ्लावर्सस्केप

51
हाँ, कंपाइलर को कुछ अतिरिक्त काम करने के लिए व्यापार करने की सुविधा देता है और इसके बजाय हम सभी को हमारे पुस्तकालय उपयोगकर्ताओं को सुविधा प्रदान करने के लिए 100000 ओवरलोड लिखते हैं। अच्छा विचार।

28
@ user562566: जब भी मैं जावा प्रोजेक्ट पर काम करता हूं, मुझे यह आभास होता है कि जावा देवों को प्रति दिन कितनी कोड लाइनों का भुगतान / माप किया जाता है
मार्क के कोवान

83

दुर्भाग्य से हाँ।

void MyParameterizedFunction(String param1, int param2, bool param3=false) {}

जावा 1.5 में इस प्रकार लिखा जा सकता है:

void MyParameterizedFunction(String param1, int param2, Boolean... params) {
    assert params.length <= 1;
    bool param3 = params.length > 0 ? params[0].booleanValue() : false;
}

लेकिन आपको कंपाइलर जेनरेट करने के बारे में कैसा महसूस होता है, इस पर निर्भर होना चाहिए

new Boolean[]{}

प्रत्येक कॉल के लिए।

कई डिफ़ॉल्ट मापदंडों के लिए:

void MyParameterizedFunction(String param1, int param2, bool param3=false, int param4=42) {}

जावा 1.5 में इस प्रकार लिखा जा सकता है:

void MyParameterizedFunction(String param1, int param2, Object... p) {
    int l = p.length;
    assert l <= 2;
    assert l < 1 || Boolean.class.isInstance(p[0]);
    assert l < 2 || Integer.class.isInstance(p[1]);
    bool param3 = l > 0 && p[0] != null ? ((Boolean)p[0]).booleanValue() : false;
    int param4 = l > 1 && p[1] != null ? ((Integer)p[1]).intValue() : 42;
}

यह C ++ सिंटैक्स से मेल खाता है, जो केवल पैरामीटर सूची के अंत में डिफ़ॉल्ट पैरामीटर की अनुमति देता है।

सिंटैक्स से परे, एक अंतर है जहां यह समय बीतने योग्य डिफ़ॉल्ट मापदंडों के लिए समय प्रकार की जाँच करता है और संकलन के दौरान C ++ प्रकार उन्हें जाँचता है।


14
चतुर, लेकिन varargs (...) का उपयोग केवल अंतिम पैरामीटर के लिए किया जा सकता है, जो डिफ़ॉल्ट पैरामीटर का समर्थन करने वाली भाषाओं की तुलना में अधिक सीमित है।
२०:१० पर २१:१०

6
यह चालाक है, लेकिन C ++ संस्करण की तुलना में थोड़ा गड़बड़ है
किसी ने

5
Java को निश्चित रूप से C # के रूप में वैकल्पिक डिफॉल्टेड मापदंडों की आवश्यकता है और अन्य लोग अनुमति देते हैं ... सिंटैक्स स्पष्ट है और मुझे लगता है कि वे इसे काफी सरलता से लागू कर सकते हैं बस सभी संभावित संयोजनों को संकलित करके ... मैं कल्पना नहीं कर सकता कि उन्होंने इसे भाषा में क्यों नहीं जोड़ा है। अभी तक!
jwl

10
किसी assertको उत्पादन कोड में कभी भी उपयोग नहीं करना चाहिए । एक अपवाद फेंक दें।
माइकल डोरस्ट

5
-1 यह वास्तव में वैराग्य के लिए नहीं है। यह एक हैक है। - इस मामले में, अधिभार का उपयोग करना अधिक पठनीय होगा (जो दुर्भाग्यपूर्ण है, क्योंकि तीन अतिरिक्त वर्ण स्रोत के 5 अतिरिक्त लाइनों की तुलना में अधिक पठनीय हैं ...)। - लेकिन जावा डिफ़ॉल्ट मापदंडों का समर्थन नहीं करता है।
BrainSlugs83

38

नहीं, लेकिन आप बहुत आसानी से उनका अनुकरण कर सकते हैं। C ++ में क्या था:

public: void myFunction(int a, int b=5, string c="test") { ... }

जावा में, यह एक अतिभारित कार्य होगा:

public void myFunction(int a, int b, string c) { ... }

public void myFunction(int a, int b) {
    myFunction(a, b, "test");
}

public void myFunction(int a) {
    myFunction(a, 5);
}

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


8
C # डिफॉल्ट वैल्यू नोटेशन का मुख्य विचार इस बॉयलरप्लेट कोडिंग से बचने के लिए ठीक है और कई के बजाय सिर्फ एक कंस्ट्रक्टर है।
Kolya इवानकोव

1
@KolyaIvankov मैं C # नहीं जानता, लेकिन मुझे C ++ पता है जहाँ तर्क समान है। मुझे नहीं पता कि क्या बेहतर है, लेकिन मुझे लगता है, वास्तव में एक ही बॉयलरप्लेट कोड कंपाइलर द्वारा C ++ / C # के मामले में उत्पन्न होता है और यह अंतिम बाइनरी में जा रहा है।
पीटर - मोनिका

5
हर प्रोग्रामिंग भाषा (विशेष रूप से) एक असेम्बलर बॉयलरप्लेट से बचने का साधन है, क्या मैं गलत हूं? सवाल केवल यह है कि यह एक आसान कार्यक्षमता देता है या नहीं।
Kolya इवानकोव

2
पहला वाक्य एक अलंकारिक प्रश्न है। दूसरे वाक्य में "सवाल" शब्द का पहले में बयानबाजी के सवाल से कोई लेना-देना नहीं है।
Kolya इवानकोव

1
अधिक विशिष्ट होने के कारण: भाषाएं ऐसे उपकरण हैं जो हमें एक तरह से प्रोग्राम लिखने की अनुमति देते हैं, जिस पर लिखा हुआ है, उस पर हमारा नियंत्रण हो सकता है। संकलन मशीन को यह बताने का एक तरीका है कि हम उससे क्या चाहते हैं। एक उपकरण अधिक उपयोगी है अगर यह हमें बॉयलरप्लेट से बचने की अनुमति देता है। वास्तव में, gnavi ने पूछा, यदि वे ठीक उसी प्रकार के बॉयलरप्लेट कोड से बच सकते हैं जो आप उत्तर के रूप में प्रस्तावित करते हैं, क्योंकि C # इसके लिए अनुमति देता है।
Kolya इवानकोव

24

आप कर सकते हैं यह स्काला में है, जो जेवीएम पर चलता है और जावा कार्यक्रमों के साथ संगत है। http://www.scala-lang.org/

अर्थात

class Foo(var prime: Boolean = false, val rib: String)  {}

58
पूरी तरह से नई भाषा लाएँ ताकि कोई आम विशेषता न हो?
ओम-नॉम-नॉम-अप

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

28
@ वाल सिर्फ इतना कह रहे हैं कि यह तोपों के साथ पक्षियों की शूटिंग की तरह है
ओम-नॉम-नॉम-

8
ओपी के सवाल से कोई लेना-देना नहीं है
भाग्य

कोटलिन में भी काम करता है। और ग्रूवी। और सी#। और जावास्क्रिप्ट। और लगभग सभी अन्य भाषाएँ जो वास्तविक लोगों और समस्याओं के लिए बनाई गई हैं।
स्पाईरो

17

नहीं , लेकिन इसे लागू करने का सबसे सरल तरीका है:

public myParameterizedFunction(String param1, int param2, Boolean param3) {

    param3 = param3 == null ? false : param3;
}

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

या टर्नरी ऑपरेटर के बजाय , आप उपयोग कर सकते हैं if:

public myParameterizedFunction(String param1, int param2, Boolean param3) {

    if (param3 == null) {
        param3 = false;
    }
}

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

2
हां, यह दृष्टिकोण अन्य विकल्पों में से सबसे अच्छा लगता है। फिर भी जावा के लिए डिफ़ॉल्ट मान अपनाना अच्छा होगा; कोटलिन ने दिखाया कि यह किया जा सकता है, इसलिए मुझे यकीन नहीं है कि ओरेकल आधुनिक युग में प्रवेश नहीं करता है, और जावा को डिजाइन करता रहता है जैसे कि यह 1990 के दशक में था। : डी
शेवी

13

मैं यहाँ स्पष्ट हो सकता है, लेकिन क्यों नहीं बस "डिफ़ॉल्ट" पैरामीटर को स्वयं लागू करें?

public class Foo() {
        public void func(String s){
                func(s, true);
        }
        public void func(String s, boolean b){
                //your code here
        }
}

डिफ़ॉल्ट के लिए, आप या तो उपयोग करेंगे

func("my string");

और यदि आप डिफ़ॉल्ट का उपयोग नहीं करना चाहते हैं, तो आप उपयोग करेंगे

func("my string", false);

11
पोस्टर में पूछा गया कि क्या यह (बल्कि बदसूरत) पैटर्न से बचा जा सकता है ... ;-) अधिक आधुनिक भाषाओं (जैसे सी #, स्काला) में आपको इस अतिरिक्त अधिभार की आवश्यकता नहीं है जो केवल कोड की अधिक लाइनें बनाता है। कुछ बिंदु तक आप इस बीच (स्थैतिक int अधिकतम (int ... सरणी) {}) में varargs का उपयोग कर सकते हैं, लेकिन वे केवल बहुत बदसूरत वर्कअराउंड हैं।
ऑफसर

2
ओवरलोडिंग बदसूरत नहीं है और इसके कई फायदे हैं, जैसे अलग-अलग तरीकों से अलग-अलग हस्ताक्षर वाले कॉल विभिन्न कार्यक्षमता का प्रदर्शन कर सकते हैं। //This is better public class Foo() { /* This does something */ public void func(String s){ //do something } /* This does something else with b */ public void func(String s, boolean b){ // b was passed } } //Than this public class Foo() { /* This does something unless b = value, then it does something else */ public void func(String s, boolean b = value){ If (b){ // Do Something } else{ // Do something else } } }
एंटनी बूथ

खैर, अगर कोई अलग व्यवहार चाहता है। यदि एकमात्र अंतर गणनाओं आदि में थोड़ा सा बदलाव है, तो यह निश्चित है कि कई हस्ताक्षर बनाने के प्रयास की बर्बादी है। चूक से समझ में आता है कि आपको उनकी आवश्यकता कहां है ... और इसकी कमी को "बेकार" आवश्यकता के रूप में वर्गीकृत नहीं किया जाना चाहिए।
कपिल

@ ओफ़लर डिफ़ॉल्ट मापदंडों का "आधुनिक भाषा" से कोई लेना-देना नहीं है। मैंने उन्हें डेल्फी में 20 साल पहले इस्तेमाल किया था और वे शायद टर्बो पास्कल में पहले से मौजूद थे।
अविश्वसनीय जन

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

8

जैसा कि स्काला का उल्लेख किया गया था, कोटलिन भी ध्यान देने योग्य है। कोटलिन फ़ंक्शन पैरामीटर में डिफ़ॉल्ट मान भी हो सकते हैं और वे अन्य मापदंडों को भी संदर्भित कर सकते हैं:

fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) {
    ...
}

स्काला की तरह, कोटलिन जेवीएम पर चलता है और इसे आसानी से मौजूदा जावा प्रोजेक्ट्स में एकीकृत किया जा सकता है।


6

नहीं।

आप किसी ऑब्जेक्ट को पास करके उसी व्यवहार को प्राप्त कर सकते हैं जिसमें स्मार्ट चूक हैं। लेकिन फिर से यह निर्भर करता है कि आपका मामला क्या है।


5

सामान्य रूप से जावा में बहुत अधिक (कोई भी) संश्लिष्ट चीनी नहीं होती है, क्योंकि वे एक सरल भाषा बनाने की कोशिश करते हैं।


26
काफी नहीं। कड़वा सच यह है कि टीम एक टाइट शेड्यूल पर थी और उसके पास सिंथैटिक शुगर के लिए समय नहीं था। कोई constऔर gotoकीवर्ड आरक्षित क्यों होगा और कोई कार्यान्वयन नहीं होगा? - विशेष रूप constसे कुछ ऐसा है जो मुझे कड़वा लगता है - finalकोई प्रतिस्थापन नहीं है और वे इसे जानते थे। - और यदि आपने कभी नहीं लागू करने के लिए शंकालु निर्णय लिया है तो आपको gotoकीवर्ड को आरक्षित करने की आवश्यकता नहीं होगी। - और बाद में जावा टीम में लेबल आधारित breakऔर continueपास्कल के रूप में शक्तिशाली बनाकर धोखा दिया goto
मार्टिन

"सरल, वस्तु-उन्मुख और परिचित" वास्तव में एक डिजाइन लक्ष्य था - oracle.com/technetwork/java/intro-141325.html
mikera

1
टॉमजेन ने कहा: "नहीं। सामान्य जावा में बहुत अधिक (कोई भी) संश्लिष्ट चीनी नहीं है, क्योंकि उन्होंने एक सरल भाषा बनाने की कोशिश की है"। तो आप कह रहे हैं कि C ++ से बहुत सारी अनावश्यक विशेषताओं को हटाने से जावा एक सरल भाषा बन जाती है, तो मुझे बताएं कि जावा में वैराडिक तरीके क्यों हैं? इसके पास varargs क्यों है? यह आवश्यक नहीं है यदि आप केवल वस्तुओं की एक सरणी का उपयोग कर सकते हैं, तो क्या मैं सही हूं? अतः भाषा से वर्ण-भेद को हटाया जा सकता है, क्योंकि यह अनावश्यक है। यह जावा को अब जो है उससे अधिक सरल बना देगा। क्या मैं सही हू? ओवरलोडिंग को भी हटाया जा सकता है, क्योंकि आपके पास प्रत्येक विधि के लिए अनंत नाम हैं।

1
और इसीलिए हमें वसंत और सामान मिला जो सरल भाषा में लेते हैं और किसी भी वास्तविक जावा प्रोजेक्ट को सिंटैक्स और बॉयलरप्लेट के एक क्लस्टर में बदल देते हैं :-)
matanster

बॉयलरप्लेट कोड और जटिल वर्कअराउंड के लिए देवों को मजबूर करना "आसान" शब्द की मेरी समझ नहीं है। myFunction (a, b = false, c = 3), यही मैं आसान कहता हूं।
स्पाईरो

5

के बजाय का उपयोग करने का:

void parameterizedMethod(String param1, int param2) {
    this(param1, param2, false);
}

void parameterizedMethod(String param1, int param2, boolean param3) {
    //use all three parameters here
}

आप एकल विधि होने से जावा की वैकल्पिक कार्यक्षमता का उपयोग कर सकते हैं:

void parameterizedMethod(String param1, int param2, @Nullable Boolean param3) {
    param3 = Optional.ofNullable(param3).orElse(false);
    //use all three parameters here
}

मुख्य अंतर यह है कि आपको nullइनपुट की अनुमति देने के लिए आदिम जावा प्रकारों के बजाय रैपर कक्षाओं का उपयोग करना होगा । Booleanके बजाय boolean, Integerके बजाय intऔर इतने पर।


4

यह समर्थित नहीं है, लेकिन कुछ सिंटैक्स चीनी के साथ पैरामीटर ऑब्जेक्ट पैटर्न का उपयोग करने जैसे कई विकल्प हैं:

public class Foo() {
    private static class ParameterObject {
        int param1 = 1;
        String param2 = "";
    }

    public static void main(String[] args) {
        new Foo().myMethod(new ParameterObject() {{ param1 = 10; param2 = "bar";}});
    }

    private void myMethod(ParameterObject po) {
    }
}

इस नमूने में हम ParameterObjectडिफ़ॉल्ट मानों के साथ निर्माण करते हैं और उन्हें वर्ग उदाहरण आरंभीकरण अनुभाग में ओवरराइड करते हैं{ param1 = 10; param2 = "bar";}



3

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

बस वर्ग, या इंटरफ़ेस में @GenerateMethodInvocationBuilder जोड़ें, और उन तरीकों में मापदंडों के लिए @Default जहां आप डिफ़ॉल्ट मान चाहते हैं। एक बिल्डर संकलित समय पर उत्पन्न होगा, डिफ़ॉल्ट मानों का उपयोग करके जो आपने अपने एनोटेशन के साथ निर्दिष्ट किया था।

@GenerateMethodInvocationBuilder
public class CarService {
 public CarService() {
 }

 public String getCarsByFilter(//
   @Default("Color.BLUE") Color color, //
   @Default("new ProductionYear(2001)") ProductionYear productionYear,//
   @Default("Tomas") String owner//
 ) {
  return "Filtering... " + color + productionYear + owner;
 }
}

और फिर आप विधियों को लागू कर सकते हैं।

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .invoke(instance);

या डिफ़ॉल्ट मानों को किसी और चीज़ में सेट करें।

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .withColor(Color.YELLOW)//
  .invoke(instance);

2

Https://stackoverflow.com/a/13864910/2323964 के समान दृष्टिकोण जो जावा 8 में काम करता है, डिफ़ॉल्ट गेटर्स के साथ एक इंटरफेस का उपयोग करना है। यह अधिक व्हाट्सएप क्रिया होगी, लेकिन यह नकली है, और यह तब बहुत अच्छा होता है जब आपके पास उदाहरणों का एक समूह होता है जहां आप वास्तव में मापदंडों पर ध्यान आकर्षित करना चाहते हैं।

public class Foo() {
    public interface Parameters {
        String getRequired();
        default int getOptionalInt(){ return 23; }
        default String getOptionalString(){ return "Skidoo"; }
    }

    public Foo(Parameters parameters){
        //...
    }

    public static void baz() {
        final Foo foo = new Foo(new Person() {
            @Override public String getRequired(){ return "blahblahblah"; }
            @Override public int getOptionalInt(){ return 43; }
        });
    }
}

2

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

int foo(int a) {
    // do something with a
    return a;
}

int foo() {
    return foo(0); // here, 0 is a default value for a
}

1

यह मैंने ऐसा किया है ... यह आपके परिभाषित पैरामीटर के खिलाफ 'वैकल्पिक तर्क' के रूप में शायद उतना सुविधाजनक नहीं है, लेकिन यह काम हो जाता है:

public void postUserMessage(String s,boolean wipeClean)
{
    if(wipeClean)
    {
        userInformation.setText(s + "\n");
    }
    else
    {
        postUserMessage(s);
    }
}

public void postUserMessage(String s)
{
    userInformation.appendText(s + "\n");
}

सूचना मैं एक ही विधि का नाम या तो एक स्ट्रिंग के साथ लागू कर सकता हूं या मैं इसे एक स्ट्रिंग और बूलियन मान के साथ लागू कर सकता हूं। इस स्थिति में, wipeClean को सही पर सेट करना मेरे TextArea के सभी पाठ को दिए गए स्ट्रिंग के साथ बदल देगा। WipeClean को गलत पर सेट करना या उसे एक साथ छोड़ देना बस TextArea को दिए गए टेक्स्ट को जोड़ देता है।

यह भी ध्यान दें कि मैं दो विधियों में कोड को नहीं दोहरा रहा हूं, मैं केवल एक जोड़ा नाम बूलियन के साथ एक नया तरीका बनाकर TextArea को रीसेट करने में सक्षम होने की कार्यक्षमता जोड़ रहा हूं।

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


1

नहीं, लेकिन हमारे पास फ़ंक्शन ओवरलोडिंग के रूप में विकल्प है।

जब कोई पैरामीटर पास नहीं होता है तो कॉल किया जाता है

void operation(){

int a = 0;
int b = 0;

} 

जब "a" पैरामीटर पारित किया गया था

void operation(int a){

int b = 0;
//code

} 

जब पैरामीटर बी पास किया जाता है

void operation(int a , int b){
//code
} 

1

इस तरह के आधा दर्जन या बेहतर मुद्दे हैं, आखिरकार, आप स्थिर कारखाने पैटर्न पर पहुंचते हैं ... उसके लिए क्रिप्टो एपीआई देखें। व्याख्या करना कठिन है, लेकिन इसे इस तरह से सोचें: यदि आपके पास एक कंस्ट्रक्टर है, डिफ़ॉल्ट या अन्यथा, घुंघराले ब्रेसिज़ से परे राज्य का प्रचार करने का एकमात्र तरीका या तो एक बूलियन है अमान्य है; (डिफ़ॉल्ट मान v असफल निर्माता के रूप में रिक्त के साथ) या फ़ील्ड उपयोगकर्ताओं से वापस प्राप्त करते समय कोई अपवाद नहीं है जो कभी भी जानकारीपूर्ण न हो।

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

मुझे लगता है कि हमें यहां क्या करने की आवश्यकता है, अशक्त के मुद्दे को डिफ़ॉल्ट मान के रूप में संबोधित किया जाता है, कुछ-कुछ स्ट्रिंग स्ट्रिंग एक = नया स्ट्रिंग (""); एक सदस्य चर के रूप में, फिर स्ट्रिंग को असाइन करने से पहले नल के लिए एक चेक कर रहा है।

जावा में कच्चे, समताप मंडलीय कंप्यूटर विज्ञान की बहुत उल्लेखनीय मात्रा।

C ++ और इतने पर वेंडर लिबास हैं, हां। बड़े पैमाने पर टूलबॉक्स के कारण जावा उन्हें बड़े पैमाने पर सर्वर से आगे निकाल सकता है। स्टैटिक इनिशियलाइज़र ब्लॉक का अध्ययन करें, हमारे साथ रहें।



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