2012-04-15 20 views
6

कहते हैं कि यह सी ++ कोड है की सुविधा देता है:जावा "पॉइंटर्स" कैसे काम करते हैं?

void change(int& x){ 
    x++; 
} 

या

void change2(int* a){ 
    *a++; 
} 

दोनों वैश्विक एक्स, सही बदल जाएगा?

तो मैं जावा में ऐसा कुछ कैसे कर सकता हूं?
विशेष रूप से, मैं एक वेक्टर ऑब्जेक्ट

पर इंगित करना चाहता हूं लेकिन चूंकि जावा में कोई पॉइंटर्स नहीं है, मुझे यकीन नहीं है कि क्या करना है।
इंटरनेट खोज से मैंने लोगों को यह कहते हुए देखा कि जावा किसी अन्य तरीके से करता है, लेकिन मुझे कोई वास्तविक उदाहरण नहीं मिला है।

सहायता के लिए धन्यवाद!

+0

जावा हमेशा मूल्य से गुजरता है। –

+0

उत्तर की संभावना है, "आप नहीं कर सकते" - लेकिन हमें प्रासंगिक जावा कोड देकर शुरू करें ... –

+1

[जावा में संदर्भ द्वारा कैसे पास किया जाए] के संभावित डुप्लिकेट (http://stackoverflow.com/questions/5614562/कैसे-पास-दर-संदर्भ-इन-जावा) –

उत्तर

12

जावा में, पॉइंटर्स के बजाए आपके पास ऑब्जेक्ट्स का संदर्भ है। आप संदर्भ द्वारा एक आदिम प्रकार को पारित नहीं कर सकते हैं, लेकिन आप किसी ऑब्जेक्ट के अंदर एक आदिम प्रकार को लपेट सकते हैं और फिर उस ऑब्जेक्ट का संदर्भ पास कर सकते हैं।

जावा Integer प्रकार प्रदान करता है जो int को लपेटता है, हालांकि यह प्रकार अपरिवर्तनीय है ताकि आप निर्माण के बाद अपना मूल्य बदल नहीं सकें। आप फिर भी अपाचे कॉमन्स से MutableInt इस्तेमाल कर सकते हैं:

void change(MutableInt x) { 
    x.increment(); 
} 

एक्स के लिए परिवर्तन फोन करने वाले को दिखाई जाएगी।


विशेष रूप से, मैं एक वेक्टर वस्तु

को इंगित करने के बारे में जब आप Vector v = ...; आप चर v करने के लिए एक वेक्टर के लिए एक संदर्भ बताए करना चाहते हैं। जावा में एक संदर्भ एक सूचक के समान है। संदर्भ वास्तव में पॉइंटर्स का उपयोग करके आंतरिक रूप से कार्यान्वित किए जाते हैं।

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

+0

मुझे इस बारे में क्या पसंद नहीं है यह है कि यह इंप्रेशन देता है कि आपको जावा में बेहद बुनियादी कुछ करने के लिए तीसरे पक्ष की lib की आवश्यकता है। मुझे पूरा यकीन है कि ओपी ** ** ** को वास्तव में MutacheInt या अपाचे कॉमन्स से कुछ और चाहिए; इसके बजाय, उसे सिर्फ मूर्खतापूर्ण जावा सीखना होगा। माना जाता है कि सवाल बेहतर जवाब देने में मुश्किल है, क्योंकि यह स्पष्ट नहीं है कि वह वास्तव में * अपना कोड क्या चाहता है। – Jonik

+0

मुझे यह भी पसंद नहीं है कि यह स्वीकार्य उत्तर है। Http://stackoverflow.com/questions/5614562/how-to-do-the-equivalent-of-pass-by-reference-for-primitives-in-java/5614630#5614630 को 4 तरीकों की पूरी तरह से स्पष्टीकरण के लिए देखें ऐसा कोई तीसरी पार्टी लाइब्रेरी आयात किए बिना करें। या ऐसा करने के एक आम तरीके के लिए dash1e का जवाब देखें। – ToolmakerSteve

1

जावा हमेशा मूल्य से गुजरता है और सी ++ भावना में कोई वैश्विक चर नहीं होता है। तो यदि आप सी ++ में ऐसा करना चाहते हैं तो आपको नया मान वापस करने की आवश्यकता है।

Thusly:

public int change(int x) { 
    return ++x; 
    // or 
    // return x + 1; 
} 

यह परीक्षण करने के लिए:

int x = 2; 

change(x); 

System.out.println(x); // returns 2 

x = change(x); 

System.out.println(x); // returns 3 

तो यह विधि change कहा जा जाने के लिए कोई मतलब नहीं है, यह calculateThisInt की तर्ज पर अधिक समझदार है।


जावा मूल्य से वस्तुएं पास करता है। लेकिन Mark Byers उल्लेख करता है कि Integer कक्षा अपरिवर्तनीय है और आप अपाचे कॉमन्स लाइब्रेरी से MutableInt का उपयोग कर सकते हैं।वर्णन करने के लिए यह कैसे काम करता है कि आप अपने उदाहरण के लिए यह अपने आप को लागू कर सकते हैं:

public class MyInt() { 

    public int i; 

    public void setInt(int i) { 
     this.i = i; 
    } 

    public int getInt() { 
     return this.i; 
    } 

    public int increment() { 
     this.i++; 
    } 

} 

आप अपने change समारोह को बदलने के लिए तर्क के रूप में ऊपर MyInt वस्तु की आवश्यकता है:

public void change(MyInt i) { 
    i.increment(); 
} 

उपयोग:

MyInt x = new MyInt(); 
x.setInt(2); 

change(x); 

System.out.println(x.getInt); // returns 3 

आपके मामले में आपबदलना चाहते हैंऑब्जेक्ट ...

public void changeVector(Vector v) { 
    // anything you do with 'v' will change it even 
    // for the scope that called this method 
} 

// Usage: 
Vector v = new Vector(); 
changeVector(v); 
// v should be changed after calling change vector method 

आशा है कि यह सब समझ में आता है।

+0

आपको वापसी ++ एक्स का उपयोग करने की आवश्यकता है; बदले x ++ की बजाय; – Chris

+0

@ क्रिस: ओह, तय। – Spoike

+0

ऑब्जेक्ट जावा में संदर्भ द्वारा पारित नहीं किए जाते हैं।किसी ऑब्जेक्ट का संदर्भ मान द्वारा पारित किया जाता है। –

4

जावा के साथ आप संदर्भ के अनुसार int जैसे आदिम प्रकारों को पारित नहीं कर सकते हैं, वे केवल मूल्य से ही पारित होते हैं।

केवल एक चीज जो आप कर सकते हैं वह ऐसा करने के लिए कलाकृतियों को ढूंढना है, क्योंकि इसके बजाय Objects संदर्भ द्वारा पारित किया जाता है। यहां दो उदाहरण हैं।

एक धारक वर्ग एकल मान की एक सरणी का उपयोग करें, इस

int[] value = new int[1]; 
value[0] = 2; 

// call a method 
obj.setValue(value); 

// and in setValue 
public void setValue(int[] value) { 
    value[0] = 5; 
} 

या दूसरा दृष्टिकोण की तरह उपयोग करें:

public class Holder<T> { 
    public T value; 
    public Holder(T value) { 
    this.value = value; 
    } 
} 

// then use it in this way 
Holder<Integer> h = new Holder<Integer>(2); 

obj.setValue(h); 

// and in setValue 
public void setValue(Holder<Integer> h) { 
    h.value = 5; 
} 

इस मामले मैं एक धारक वर्ग जेनरिक के साथ लागू करता है का उपयोग में है, लेकिन आप कर सकते हैं एक साधारण धारक भी, केवल पूर्णांक के लिए। उदाहरण के लिए:

public class IntHolder { 
    public int value; 
    public IntHolder(int value) { 
    this.value = value; 
    } 
} 
+0

प्रिय SmRndGuy, यह वह उत्तर है जिसे आप ढूंढ रहे हैं। (पीएस: मुझे होल्डर क्लास के बारे में पता नहीं था, इसलिए धन्यवाद dash1e।) – guness

+0

@bluebrain ध्यान दें, जावा मानक वर्ग नहीं है, आपको अपने होल्डर को अपने आप लिखना है, लेकिन यह बहुत आसान है। शायद, कभी-कभी, आप विभिन्न पुस्तकालयों में धारकों को पा सकते हैं क्योंकि यह उस समस्या को हल करने का एक सामान्य तरीका है। – dash1e

+0

वह सामान्य 'धारक' वर्ग "रैपर" करने का एक अच्छा तरीका है। – Spoike

0

जबकि आप एक वस्तु है कि एक समारोह के लिए पारित किया गया है को बदल नहीं सकते, तो आप अपने राज्य सीधे खेतों में फेरबदल या तरीकों को फोन करके बदल सकते हैं। यदि आपको एक आदिम के लिए पॉइंटर की तरह कुछ चाहिए, तो इसे किसी ऑब्जेक्ट में लपेटें। अपने कोड का पालन करने के लिए, आप ऐसा कर सकता है: तो फिर कहीं और

public class IntPointer { 
    public int value; 
    public IntPointer(int value) { 
     this.value = value; 
    } 
} 

आप कह सकते हैं:

public static void change(IntPointer ipoint) { 
    ipoint.value++; 
} 
public static void main(String[] args) { 
    IntPointer a = new IntPointer(10); 
    change(a); 
} 

इसमें कुछ समय अजीब लग सकता है लेकिन यह नहीं आप जितनी बार मेरे लिए आ गया है मुझे लगता है। ,

public static void main(String[] args) { 
    ABPair ab = new ABPair(); 
    if (ACondition) { 
     ab.changeA(); 
    } 
} 

दूसरे शब्दों में, अपने डेटा को पहले से ही वस्तु के कुछ प्रकार में लिपटे हो जाता है:

public class ABPair { 
    private int a = 0; 
    private int b = 0; 
    public static void changeA() { 
     a++; 
    } 
    public static void changeB() { 
     b++; 
    } 
} 

ताकि कहीं और मैं कह सकता हूँ: मैं अधिक कुछ इस तरह करने की संभावना होगी और मैं किसी भी बदलाव में मध्यस्थता करने के लिए डेटा ऑब्जेक्ट के तरीकों का उपयोग करता हूं।

0

दोनों वैश्विक x को बदल देंगे, है ना?

तो मैं जावा में ऐसा कुछ कैसे कर सकता हूं?विशेष रूप से, मैं एक वेक्टर वस्तु

सवाल का बात करने के लिए चाहते हैं कुछ हद तक अस्पष्ट है, लेकिन मैं धारणा है कि आप अंततः चाहते मिला एक वैश्विक Vector है कि आप में सामान रख सकते हैं?

ऐसा करने के कई तरीके हैं, लेकिन सबसे आसान में से एक है एक वर्ग में स्थिर फ़ील्ड, इसे एक्सेस करने के लिए सार्वजनिक स्थैतिक तरीकों के साथ। (या बस एक सार्वजनिक स्थिर क्षेत्र है जो सीधे पहुँचा है, लेकिन यह वास्तव में जावा में मुहावरेदार नहीं होगा।)

public class Foo { 
    private static List<Integer> globalVector = new Vector<Integer>(); 

    public static void add(int number){ 
     globalVector.add(number); 
    } 

    // ... plus whatever other accessors to the global list that you need 
} 
कहीं भी किसी और कोड में

:

Foo.add(23); // modifies the global vector 

(Btw, Vector थोड़े अप्रचलित है , और आम तौर पर हम अपने स्थान पर ऐरेलिस्ट का उपयोग करेंगे। जैसा कि जावाडोक कहते हैं, इसे सूची इंटरफ़ेस को लागू करने के लिए फिर से लगाया गया है, जिसे मैंने उदाहरण में भी उपयोग किया था।)

+0

** अस्वीकरण **: मैंने ओपी चाहता था कि पूरी तरह से गलत व्याख्या की हो, और अगर यह मामला सामने आता है तो इसे हटा देगा। वास्तव में प्रश्न यह स्पष्ट होना चाहिए कि ओपी वास्तव में अपने कोड के साथ हासिल करना चाहता है। – Jonik

0

जावा "संदर्भ" कहता है। संदर्भ सी/सी ++ में पॉइंटर्स की तरह बहुत काम करते हैं - भाषाओं की तरह। वे उन भाषाओं में "संदर्भ" काम के समान तरीके से कार्य नहीं करते हैं।

जावा में सी में एक सूचक और एक संदर्भ के बीच प्रमुख अंतर हैं:

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

तो जावा संदर्भों को "प्रतिबंधित पॉइंटर्स" कहा जा सकता है।

संबंधित मुद्दे