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




methods parameters (16)

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

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

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

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

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

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


https://.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; }
        });
    }
}

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

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

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

public MyParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

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

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

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

public MyParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

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


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

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";} को डिफ़ॉल्ट मानों के साथ { param1 = 10; param2 = "bar";} हैं और क्लास इंस्टेंस प्रारंभिक अनुभाग { param1 = 10; param2 = "bar";} { param1 = 10; param2 = "bar";}


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

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;
}

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

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


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

अर्थात

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

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

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

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


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

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

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

func ("मेरी स्ट्रिंग");

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

func ("मेरी स्ट्रिंग", झूठी);


नहीं।

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


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

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

void operation(){

int a = 0;
int b = 0;

} 

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

void operation(int a){

int b = 0;
//code

} 

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

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

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

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 को सही करने के लिए सेटिंग को मेरे टेक्स्ट एरिया में दिए गए स्ट्रिंग के साथ सभी टेक्स्ट को प्रतिस्थापित कर देगा। WipeClean को गलत पर सेट करना या इसे सभी को छोड़कर बस टेक्स्टएरिया को प्रदान किया गया टेक्स्ट जोड़ता है।

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

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


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

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

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

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


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

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


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

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

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


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

क्लास, या इंटरफ़ेस में @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);

इस समाधान का प्रयास करें:

public int getScore(int score, Integer... bonus)
{
    if(bonus.length > 0)
    {
        return score + bonus[0];
    }

    return score;
}




method-overloading