जावा में आप वर्गास का उपयोग कब करते हैं?


192

मुझे डर लगता है। मुझे नहीं पता कि उनके लिए क्या उपयोग करना है।

साथ ही, लोगों को जितने चाहें उतने तर्क वितर्क करने देना खतरनाक लगता है।

एक संदर्भ का उदाहरण क्या है जो उनका उपयोग करने के लिए एक अच्छी जगह होगी?


3
मैं यह नहीं देखता कि यह "खतरनाक" क्यों होगा। यह अलग-अलग तर्कों के साथ कई बार बड़ी विधि कहलाने से ज्यादा खतरनाक नहीं है। क्या आपको स्टैक के साथ चिंता है? तब आपको ऐसा नहीं करना चाहिए, क्योंकि वैरिएज़ को सरणियों के लिए मैप किया जाता है जो संदर्भ द्वारा पारित किए जाते हैं।
jfpoilpret

66
बस इसमें झंकार करना चाहता था: आपके द्वारा पूरी तरह से आरामदायक (अभी तक) भाषा सुविधाओं से बचने के साथ कुछ भी गलत नहीं है। उन सुविधाओं का उपयोग करने से बेहतर है जिन्हें आप नहीं समझते हैं! ;)
स्टीवन

2
अज्ञात से डरना सामान्य है। यहाँ वैरिकाज़ के बारे में और अधिक पढ़ने के लिए डॉक्स.कोरल . com/javase/tutorial/java/javaOO/arguet.html पर जाएँ । आप देखेंगे, कि varargs को डरने की कोई बात नहीं है। वर्गर उपयोगी होते हैं। वार्गर्स का उपयोग करने का तरीका जानने से आपको [PrintStream.format] (" docs.oracle.com/javase/7/docs/api/java/io/… , java.lang.Oject ...)" जैसी विधियों को लिखने की सुविधा मिलती है । ) :)।
डेवलपर Marius ėilėnas 8

1
यह वार्गर्स की आलोचना नहीं है, लेकिन वास्तव में "डरने" के लिए कुछ कारण है (जब तक कि आप वेरिएग की सीमाओं को ठीक से नहीं समझते हैं); यही कारण है कि @SafeVarargs एनोटेशन मौजूद है। stackoverflow.com/a/14252221/1593924
जॉन कॉम्ब्स

जवाबों:


150

Varargs किसी भी विधि के लिए उपयोगी होते हैं जिन्हें वस्तुओं की अनिश्चित संख्या से निपटने की आवश्यकता होती है । एक अच्छा उदाहरण है String.format। प्रारूप स्ट्रिंग किसी भी संख्या में मापदंडों को स्वीकार कर सकती है, इसलिए आपको किसी भी संख्या में ऑब्जेक्ट को पास करने के लिए एक तंत्र की आवश्यकता होती है।

String.format("This is an integer: %d", myInt);
String.format("This is an integer: %d and a string: %s", myInt, myString);

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

79

अंगूठे का एक अच्छा नियम होगा:

"किसी भी विधि (या निर्माणकर्ता) के लिए varargs का उपयोग करें जिसे इनपुट के रूप में T (जो भी प्रकार T हो सकता है) की एक सरणी की आवश्यकता है"।

इससे इन तरीकों से कॉल करना आसान हो जाएगा (कोई ज़रूरत नहीं है) new T[]{...} )।

आप एक List<T>तर्क के साथ विधियों को शामिल करने के लिए इस नियम का विस्तार कर सकते हैं , बशर्ते कि यह तर्क केवल इनपुट के लिए है (यानी, सूची विधि द्वारा संशोधित नहीं है)।

इसके अतिरिक्त, मैं उपयोग करने से बचना चाहूँगा f(Object... args)क्योंकि इसकी अस्पष्ट अस्पष्ट एपीआई के साथ प्रोग्रामिंग की ओर फिसल जाता है।

उदाहरणों के संदर्भ में, मैंने इसका उपयोग DesignGridLayout में किया है , जहां मैं JComponentएक कॉल में कई s जोड़ सकता हूं :

layout.row().grid(new JLabel("Label")).add(field1, field2, field3);

ऐड () विधि के ऊपर कोड के रूप में परिभाषित किया गया है add(JComponent... components)

अंत में, इस तरह के तरीकों के कार्यान्वयन को इस तथ्य का ध्यान रखना चाहिए कि इसे एक खाली वैरग के साथ कहा जा सकता है! यदि आप कम से कम एक तर्क थोपना चाहते हैं, तो आपको एक बदसूरत चाल का उपयोग करना होगा:

void f(T arg1, T... args) {...}

मैं इस चाल को बदसूरत मानता हूं क्योंकि विधि का क्रियान्वयन सिर्फ T... argsइसके तर्कों की सूची में होने से कम सीधा होगा ।

उम्मीद है कि इस तरह के रूपांतरों के बारे में बात को स्पष्ट करने में मदद मिलेगी।


1
क्या आपने if (args.length == 0) throw new RuntimeException("foo");इसके बजाय एक पूर्व शर्त जाँच जोड़ने पर विचार किया? (चूंकि कॉलर अनुबंध का उल्लंघन कर रहा था)
मीका विडेनमैन

24
ठीक है, एक अच्छा एपीआई का उद्देश्य संभव के रूप में जल्दी से दुरुपयोग को रोकने के लिए है, इसलिए जब यह संभव हो, तो संकलन समय पर, इसलिए void f(T arg1, T... args)हमेशा इसके लिए सुझाव यह सुनिश्चित करता है कि इसे बिना तर्क के कभी नहीं बुलाया जाए, बिना रनटाइम तक इंतजार किए बिना।
jfpoilpret 19

मुझे लगता है कि ज्यादातर समय केवल एक तर्क के साथ एक कार्य के लिए एक कॉल, जिसमें कोई तर्क नहीं है, केवल कुछ भी नहीं करने के लिए राशि होगी। मुद्दा यह है कि एक वार्गस फ़ंक्शन के लिए कोई तर्क प्रदान करना सबसे अधिक संभावना है कि वे काफी नुकसान नहीं करेंगे।
वर्ल्डसेडर

Varargs उपयोगी हैं, लेकिन वे किसी सरणी का उपयोग करने के बराबर नहीं हैं। वर्गास गैर-पुन: परिवर्तनीय हैं। इसलिए, जेनेरिक की तरह, वे प्रकार के क्षरण से प्रभावित होते हैं जो नौकरी के आधार पर अस्वीकार्य बाधा हो सकती है।
जूलियन

34

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

मेरे ऐप में बहुत अधिक हर वर्ग में एक विधि डिबगप्रिंट () है:

private void debugPrint(Object... msg) {
    for (Object item : msg) System.out.print(item);
    System.out.println();
}

फिर, कक्षा के तरीकों के भीतर, मेरे पास निम्नलिखित की तरह कॉल हैं:

debugPrint("for assignment ", hwId, ", student ", studentId, ", question ",
    serialNo, ", the grade is ", grade);

जब मैं संतुष्ट हो जाता हूं कि मेरा कोड काम कर रहा है, तो मैं डिबगप्रिंट () विधि में कोड को टिप्पणी करता हूं ताकि लॉग में बहुत अधिक बाहरी और अवांछित जानकारी न हो, लेकिन मैं व्यक्तिगत कॉल को डिबगप्रिंट () के लिए छोड़ सकता हूं। बाद में, यदि मुझे कोई बग मिल जाता है, तो मैं बस डिबगप्रिंट () कोड को अनसुना कर देता हूं, और डिबगप्रिंट () पर मेरे सभी कॉल पुन: सक्रिय हो जाते हैं।

बेशक, मैं बस के रूप में आसानी से चर सकते हैं और इसके बजाय निम्नलिखित कर सकते हैं:

private void debugPrint(String msg) {
    System.out.println(msg);
}

debugPrint("for assignment " + hwId + ", student " + studentId + ", question "
    + serialNo + ", the grade is " + grade);

हालाँकि, इस मामले में, जब मैं डीबगप्रिंट () कोड के बारे में टिप्पणी करता हूं, तो सर्वर को अभी भी हर कॉल में सभी वेरिएबल्स को डीबगप्रिंट () तक पहुंचाने की परेशानी से गुजरना पड़ता है, भले ही परिणामी स्ट्रिंग के साथ कुछ भी नहीं किया गया हो। यदि मैं varargs का उपयोग करता हूं, हालांकि, सर्वर को केवल एक सरणी में रखना होगा इससे पहले कि यह पता चले कि उसे उनकी आवश्यकता नहीं है। बहुत समय बच जाता है।


4
आप प्रतिबिंब का उपयोग करके किसी भी ऑब्जेक्ट को प्रिंट करने के लिए सुपरक्लास में एक डिबग विधि को लागू कर सकते हैं।
लूलिस मार्टिनेज

12

जब हम एक विधि में पारित होने वाले तर्कों की संख्या के बारे में अनिश्चित होते हैं, तो वैराग का उपयोग किया जा सकता है। यह पृष्ठभूमि में अनिर्दिष्ट लंबाई के मापदंडों का एक सरणी बनाता है और ऐसे पैरामीटर को रनटाइम में एक सरणी के रूप में माना जा सकता है।

यदि हमारे पास एक ऐसी विधि है जिसे विभिन्न प्रकार के मापदंडों को स्वीकार करने के लिए अधिभारित किया जाता है, तो विधि को अलग-अलग समय में अधिभारित करने के बजाय, हम बस वार्गस अवधारणा का उपयोग कर सकते हैं।

इसके अलावा जब पैरामीटर का प्रकार भिन्न होता है तो "ऑब्जेक्ट ... टेस्ट" का उपयोग करके कोड को बहुत सरल किया जाएगा।

उदाहरण के लिए:

public int calculate(int...list) {
    int sum = 0;
    for (int item : list) {
        sum += item;
    }
    return sum;
}

यहाँ परोक्ष रूप से int प्रकार (सूची) की एक सरणी को पैरामीटर के रूप में पारित किया जाता है और कोड में एक सरणी के रूप में माना जाता है।

इस लिंक को बेहतर तरीके से समझने के लिए (इस अवधारणा को स्पष्ट रूप से समझने में इससे मुझे बहुत मदद मिली): http://www.javadb.com/use-varargs-in-java

पुनश्च: यहां तक ​​कि मैं varargs का उपयोग करने से डरता था जब मैंने इसे बंद नहीं किया था। लेकिन अब मुझे इसकी आदत है। जैसा कि कहा जाता है: "हम ज्ञात से चिपके रहते हैं, अज्ञात से डरते हैं", इसलिए बस इसे जितना हो सके उतना उपयोग करें और आप भी इसे पसंद करना शुरू कर देंगे :)


4
सी # वर्णों के बराबर "परम" है। यह भी एक ही काम करता है और मापदंडों की चर संख्या को स्वीकार करता है। इसे बेहतर समझ के लिए देखें: dotnetperls.com/params
Sarvan

11

वर्गास जावा संस्करण 1.5 में जोड़ा गया फीचर है।

इसका उपयोग क्यों करें?

  1. क्या होगा, यदि आप किसी विधि के लिए पास होने के लिए तर्कों की संख्या नहीं जानते हैं?
  2. क्या होगा, अगर आप एक विधि में असीमित संख्या में तर्क पारित करना चाहते हैं?

यह कैसे काम करता है?

यह दिए गए तर्कों के साथ एक सरणी बनाता है और विधि के लिए सरणी को पास करता है।

उदाहरण :

public class Solution {



    public static void main(String[] args) {
        add(5,7);
        add(5,7,9);
    }

    public static void add(int... s){
        System.out.println(s.length);
        int sum=0;
        for(int num:s)
            sum=sum+num;
        System.out.println("sum is "+sum );
    }

}

आउटपुट:

2

योग 12 है

3

राशि 21 है


6

मेरे पास एक वैराग से संबंधित भय भी है:

यदि कॉलर विधि के लिए एक स्पष्ट सरणी में गुजरता है (कई मापदंडों के विपरीत), तो आप उस सरणी के लिए एक साझा संदर्भ प्राप्त करेंगे।

यदि आपको इस सरणी को आंतरिक रूप से संग्रहीत करने की आवश्यकता है, तो आप कॉलर को बाद में बदलने में सक्षम होने से बचने के लिए पहले इसे क्लोन करना चाह सकते हैं।

 Object[] args = new Object[] { 1, 2, 3} ;

 varArgMethod(args);  // not varArgMethod(1,2,3);

 args[2] = "something else";  // this could have unexpected side-effects

हालांकि यह वास्तव में किसी भी प्रकार की वस्तु में गुजरने से अलग नहीं है, जिसकी स्थिति बाद में बदल सकती है, क्योंकि सरणी आमतौर पर (सरणी के बजाय कई तर्कों के साथ कॉल के मामले में) संकलक द्वारा बनाई गई एक ताजा एक आंतरिक रूप से जिसे आप सुरक्षित रूप से बना सकते हैं उपयोग, यह निश्चित रूप से अप्रत्याशित व्यवहार है।


1
सही है, लेकिन यह उदाहरण थोड़ा दूर की कौड़ी लगता है। क्या यह संभावना है कि लोग आपके एपीआई का इस तरह उपयोग करेंगे?
jfpoilpret

2
आप कभी नहीं जानते ... और विशेष रूप से जब तर्कों की संख्या को कॉलिंग साइड पर हार्ड-कोड नहीं किया जाता है, लेकिन यह भी कहा जाता है कि लूप में एक सूची में कहा जाता है, एक सरणी में गुजरना यह सब असामान्य नहीं है।
थिलो

5
मुझे लगता है कि आपका उपयोग-मामला उदाहरण है, आम तौर पर बोलना, संभावना नहीं है। कोई यह तर्क दे सकता है कि आपके एपीआई को इनपुट एरे का उपयोग इस तरह से नहीं करना चाहिए, और यदि ऐसा होता है, तो उसे इसका दस्तावेज बनाना चाहिए।
लॉरेंस डोल

दोनों का समर्थन करने के लिए विधि अधिभार; argMethod (ऑब्जेक्ट .. objList) argMethod (ऑब्जेक्ट [] objList)
thetoolman

2
@thetoolman: मुझे नहीं लगता कि यह संभव है। इसे डुप्लिकेट विधि माना जाएगा।
थिलो

1

मैं अक्सर ऐसे निर्माणकर्ताओं के लिए varargs का उपयोग करता हूं जो किसी प्रकार की फ़िल्टर ऑब्जेक्ट ले सकते हैं। उदाहरण के लिए, Hadoop पर आधारित हमारे सिस्टम का एक बड़ा हिस्सा एक Mapper पर आधारित है जो JSON के लिए क्रमांकन और आइटम के डीरिएलाइज़ेशन को संभालता है, और कई प्रोसेसर को लागू करता है जो प्रत्येक सामग्री का एक आइटम लेते हैं और इसे संशोधित करते हैं और इसे वापस करते हैं, या अशक्त करते हैं। अस्वीकार करना।


1

Var-Args के जावा डॉक में, यह var args का उपयोग काफी स्पष्ट है:

http://docs.oracle.com/javase/1.5.0/docs/guide/language/varargs.html

उपयोग के बारे में यह कहता है:

"तो आपको वेरिएग का उपयोग कब करना चाहिए? एक ग्राहक के रूप में, जब भी एपीआई उन्हें ऑफर करता है, तो आपको उनका लाभ उठाना चाहिए। कोर एपीआई में महत्वपूर्ण उपयोगों में प्रतिबिंब, संदेश स्वरूपण और नई प्रिंट सुविधा शामिल है। एपीआई डिजाइनर के रूप में, आपको उनका उपयोग करना चाहिए। विरल रूप से, केवल जब लाभ वास्तव में सम्मोहक होता है। आम तौर पर बोलना, आपको एक varargs पद्धति को अधिभार नहीं देना चाहिए, या प्रोग्रामर के लिए यह पता लगाना मुश्किल होगा कि कौन सा ओवरलोडिंग कहा जाता है। "

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