क्या मैं जावा में संदर्भ द्वारा पैरामीटर पारित कर सकता हूं?


जवाबों:


225

जावा भ्रमित कर रहा है क्योंकि सब कुछ मूल्य द्वारा पारित किया गया है । हालाँकि संदर्भ प्रकार के एक पैरामीटर के लिए (अर्थात आदिम प्रकार का पैरामीटर नहीं) यह संदर्भ ही है जिसे मूल्य द्वारा पारित किया जाता है, इसलिए यह पास-बाय-संदर्भ प्रतीत होता है (और लोग अक्सर दावा करते हैं कि यह है)। यह मामला नहीं है, जैसा कि निम्नलिखित द्वारा दिखाया गया है:

Object o = "Hello";
mutate(o)
System.out.println(o);

private void mutate(Object o) { o = "Goodbye"; } //NOT THE SAME o!

Helloकंसोल पर प्रिंट होगा । यदि आप उपरोक्त कोड को प्रिंट करना चाहते हैं तो एक स्पष्ट संदर्भGoodbye का उपयोग इस प्रकार है:

AtomicReference<Object> ref = new AtomicReference<Object>("Hello");
mutate(ref);
System.out.println(ref.get()); //Goodbye!

private void mutate(AtomicReference<Object> ref) { ref.set("Goodbye"); }

48
इसके अलावा, लंबाई 1 की एक सरणी का उपयोग एक संदर्भ बनाने के लिए किया जा सकता है यदि आप वास्तव में लोगों को भ्रमित करना चाहते हैं :)
क्रिस्टोफर

2
परमाणु ऊर्जा और संबंधित कक्षाएं (एटोमिकइंटर) इस तरह के संचालन के लिए सर्वश्रेष्ठ हैं
नवीन

3
AtomicReference एक ओवरकिल है, आप जरूरी नहीं कि वहां मेमोरी बैरियर चाहते हैं, और वे आपको खर्च कर सकते हैं। ऑब्जेक्ट बनाते समय उपयोग किए जाने वाले वाष्पशील चर के कारण JRuby को perfomance समस्या थी। सरणी को एक तदर्थ संदर्भ के रूप में उपयोग करने का विकल्प मेरे लिए काफी अच्छा लगता है, और मैंने इसे एक से अधिक बार उपयोग किया है।
एलाजार लीबोविच

मुझे नहीं लगता कि यह भ्रामक है, हालांकि यह सामान्य व्यवहार है। ढेर प्रकार ढेर पर मौजूद हैं और संदर्भ प्रकार ढेर पर मौजूद हैं, लेकिन संदर्भ प्रकार के लिए संदर्भ ढेर पर भी मौजूद हैं। इस प्रकार आप हमेशा स्टैक पर मूल्य के साथ काम करते हैं। मेरा मानना ​​है कि यहां सवाल यह था कि क्या स्टैक से संदर्भ को पारित करना संभव है जो कुछ अन्य मूल्य पर भी है जो स्टैक पर भी है। या अन्य संदर्भ का संदर्भ पास करें जो कुछ मूल्य पर इंगित करता है जो ढेर पर रहता है?
एओमॉर्फ

यह मैं महान जानकारी मैं सरणियों का उपयोग कर रहा था, लेकिन ऐसा लगता है कि कुछ काम के लिए बनाया गया है। मैं इस बनाम arrays के प्रदर्शन के बारे में नहीं जानता, लेकिन अगर एक प्रदर्शन में महत्वपूर्ण लूप
स्टीवे

65

क्या मैं जावा में संदर्भ द्वारा पैरामीटर पारित कर सकता हूं?

नहीं।

क्यों ? जावा में विधियों के लिए तर्क देने का केवल एक ही तरीका है: मूल्य से।

ध्यान दें:

प्राथमिकताओं के लिए यह समझना आसान है: आपको मूल्य की एक प्रति मिलती है।

अन्य सभी के लिए आपको संदर्भ की एक प्रति मिलती है और इसे मूल्य से गुजरना भी कहा जाता है।

यह इस चित्र में है:

यहाँ छवि विवरण दर्ज करें


25

जावा में रेफ के समान भाषा स्तर पर कुछ भी नहीं है । जावा में केवल मूल्य शब्दार्थ से गुजर रहा है

जिज्ञासा के लिए आप जावा में रेफ-जैसे शब्दार्थ को लागू कर सकते हैं बस अपनी वस्तुओं को एक उत्परिवर्ती कक्षा में लपेट सकते हैं:

public class Ref<T> {

    private T value;

    public Ref(T value) {
        this.value = value;
    }

    public T get() {
        return value;
    }

    public void set(T anotherValue) {
        value = anotherValue;
    }

    @Override
    public String toString() {
        return value.toString();
    }

    @Override
    public boolean equals(Object obj) {
        return value.equals(obj);
    }

    @Override
    public int hashCode() {
        return value.hashCode();
    }
}

परीक्षण का मामला:

public void changeRef(Ref<String> ref) {
    ref.set("bbb");
}

// ...
Ref<String> ref = new Ref<String>("aaa");
changeRef(ref);
System.out.println(ref); // prints "bbb"

इसके बजाय java.lang.ref.eference का उपयोग क्यों नहीं किया गया?
हार्डकोडेड

java.lang.ref.eference में कोई सेट विधि नहीं है, यह परिवर्तनशील नहीं है
dfa

क्यों नहीं AtomicReference(गैर-आदिम के लिए) का उपयोग करें? या AtomicSomething(जैसे AtomicBoolean:) आदिम के लिए?
अरविन

दुर्भाग्य से, <T> आदिम प्रकारों को स्वीकार नहीं करता है। इसे करना चाहेंगे: Ref <int>
jk7

1
@ jk7 उपयोग करने के लिए यह वास्तव में महत्वपूर्ण पर्याप्त है intके बजाय Integer, boolके बजाय Booleanऔर इतने पर? यानी, रैपर क्लास (जो सिंटैक्स के बारे में चिंता करने पर स्वचालित रूप से अपरिवर्तित होती हैं) काम नहीं करती हैं?
पॉल स्टेलियन

18

जेम्स गोसलिंग से "द जावा प्रोग्रामिंग लैंग्वेज" में:

"... जावा में बिल्कुल एक पैरामीटर पासिंग मोड है - मान से पास - और वह चीजों को सरल रखता है। .."


2
भाषा देवता के उच्चारण को उत्तर घोषित किया जाना चाहिए।
25:13

3
@ingyhere:: The pronouncement of the language god should be declared the answerवास्तव में नहीं। जावा के निर्माता क्या सोचते हैं या विश्वास करते हैं, इसके बावजूद, निरपेक्ष उत्तर भाषा विनिर्देश के एक उद्धरण से आएगा।
10

1
वास्तव में यह जेएलएस में है, खंड 8.4.1 में , और जेएलएस गोसलिंग को पहले लेखक के रूप में उद्धृत करता है: "जब विधि या निर्माता को आमंत्रित किया जाता है (.1215.12), वास्तविक तर्क अभिव्यक्तियों के मान नए बनाए गए पैरामीटर पैरामीटर को प्रारंभ करते हैं, प्रत्येक विधि या निर्माता के शरीर के निष्पादन से पहले, घोषित प्रकार। "
निगलना

बिल्कुल सही। कम प्रतिनिधि सदस्यों से व्यंग्य सहायक नहीं है।
duffymo

11

मुझे नहीं लगता कि आप कर सकते हैं। आपका सबसे अच्छा विकल्प उस चीज़ को एनकैप्सुलेट करना हो सकता है जिसे आप किसी अन्य श्रेणी के उदाहरण पर "रेफरी" से पास करना चाहते हैं, और (बाहरी) वर्ग के संदर्भ (मूल्य के अनुसार) को पास करें। मेरा क्या मतलब है अगर आप वह समझ सकें...

यानी आपका तरीका उस ऑब्जेक्ट की आंतरिक स्थिति को बदल देता है जो इसे पारित किया जाता है, जो तब कॉलर को दिखाई देता है।


7

जावा हमेशा मान से पास होता है।

जब आप किसी आदिम को पास करते हैं तो यह मान की एक प्रति है, जब आप एक वस्तु को पास करते हैं तो यह संदर्भ सूचक की एक प्रति है।


4

एक अन्य विकल्प एक सरणी का उपयोग करना है, उदाहरण के लिए, void method(SomeClass[] v) { v[0] = ...; } लेकिन 1) विधि को लागू करने से पहले सरणी को आरंभीकृत किया जाना चाहिए, 2) अभी भी कोई इस तरह से स्वैप विधि को लागू नहीं कर सकता है ... इस तरह से JDK में उपयोग किया जाता है, जैसे java.util.concurrent.atomic.AtomicMarkableReference.get(boolean[])

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