2013-07-18 12 views
6

मैं इस सरल varargs विधि है जो सूची में प्रत्येक आइटम बांटता है:वरर्ग विधि अपनी प्रतिलिपि के बजाय कॉलर की सरणी को संशोधित करती है?

import java.util.*; 
class A { 
    static long f(long... xs) { 
     Arrays.sort(xs); 
     long y = 100000000; 
     for (int i = xs.length - 1; i >= 0; i--) 
     y /= xs[i]; 
     return y; 
    } 
    static { 
     System.out.println(f(5,2,6,3,9,3,13,4,5)); 
     long[] xs = new long[]{5,2,6,3,9,3,13,4,5}; 
     System.out.println(Arrays.toString(xs)); 
     System.out.println(f(xs)); 
     System.out.println(Arrays.toString(xs)); 
    } 
} 

मैं सरणी की एक प्रतिलिपि पारित करने के लिए उम्मीद थी यह, लेकिन जाहिरा तौर पर यह किसी भी तरह, सरणी मैं में पारित संशोधित है बजाय इसके खुद स्थानीय प्रतिलिपि:

$ javac A.java && java A 
79 
[5, 2, 6, 3, 9, 3, 13, 4, 5] 
79 
[2, 3, 3, 4, 5, 5, 6, 9, 13] 

तो मैं इस साधारण परीक्षण कार्यक्रम ने लिखा है:

class B { 
    static void f(Object... os) { 
     System.out.println(os); 
    } 
    static { 
     Object os = new Object[]{1,2,3}; 
     System.out.println(os); 
     f(os); 
    } 
} 

और यह मैं क्या उम्मीद करता है, यह वस्तु सरणी bef क्लोन अयस्क f (इसलिए अलग वस्तु पहचानकर्ता) में इसे पारित:

$ javac B.java && java B 
[Ljava.lang.Object;@1242719c 
[Ljava.lang.Object;@4830c221 

तो फिर A फोन करने वाले का बजाय सरणी अपनी एक प्रतिलिपि को संशोधित करने में f है?

+4

जावा प्रतियां मान द्वारा संदर्भ। जब तक आप इसे स्पष्ट रूप से नहीं करते हैं, तब तक यह कभी भी कॉपी या क्लोन ऑब्जेक्ट्स और न ही तर्कों (या किसी अन्य स्थिति) के रूप में सरणी करता है। –

उत्तर

14

ऐसा लगता है कि आप अपने आप को यहाँ धोखा दिया गया है जैसे:

Object os = new Object[]{1,2,3}; 
System.out.println(os); 
f(os); 

os के बाद से Object के रूप में लिखा गया है, यह varargs सरणी के पहले तत्व के रूप में व्याख्या हो जाता है। विधि में क्या हो जाता है वास्तव में एक नया Object[] है जिसका एकल तत्व आपका Object[] है।

आप निम्नलिखित करते हैं, यह एक ही उदाहरण प्रिंट होगा:

Object[] os = new Object[]{1,2,3}; 
System.out.println(os); 
f(os); 

f विधि आदेश गारंटी नहीं है कि एक सरणी फोन करने वाले प्रतिसाद नहीं द्वारा में पारित में सरणी के ही एक रक्षात्मक प्रतिलिपि बनाने की आवश्यकता होगी संशोधित नहीं है। चूंकि arshajii बताते हैं, varargs सबसे महत्वपूर्ण सरणी पैरामीटर हैं, एक तर्क सूची दिया गया है जब एक नया सरणी बनाने के "बोनस" व्यवहार के साथ।

वैसे भी आप प्रतिलिपि बनाने के लिए Arrays.copyOf का उपयोग कर सकते हैं, जो प्रतिनिधि (कम प्रकार-सुरक्षित) System.arraycopy पर प्रतिनिधि करता है।

+4

+1 अच्छा पकड़ो। यह उल्लेखनीय है कि एक varargs विधि * बिल्कुल * समान समतुल्य विधि के समान होती है जो एक सरणी पैरामीटर लेती है, सिवाय इसके कि जब आप varargs विधि में एकाधिक तर्क पारित करते हैं, तो आपके लिए एक सरणी बनाई जाती है। – arshajii

-1

अंत में, एक सरणी एक वस्तु है, इसलिए आप इसकी सामग्री की बजाय सरणी संदर्भ को संशोधित नहीं करते हैं।

+1

हां, लेकिन वह एक अलग सरणी की सामग्री को संशोधित करता है। और ये प्राइमेटिव हैं, जिनके संदर्भ नहीं हैं। – f1sh

+0

@ f1sh ओपी विधि में सरणी मानों को संशोधित कर रहा है, इसलिए इसे सरणी पर कॉल करने के बाद इसकी सामग्री संशोधित की जाएगी। –

3

varargs एक सरणी प्रकार है, लेकिन सिंटैक्टिक चीनी के साथ तत्वों को अलग-अलग पैरामीटर के रूप में अलग किए जाने पर ऑन-द-फ्लाई सरणी निर्माण की अनुमति देता है।

है यही कारण है कि, इन दो हस्ताक्षर समान हैं:

static long f(long... xs) { 
static long f(long[] xs) { 

छोड़कर varargs एक सरणी

अगर आप पर बाईपास बेशक सरणी संशोधित हो जाएगी के बजाय अलग तत्वों के साथ कहा जा सकता है कि -थ-फ्लाई सृजन और पास करने के लिए स्वयं को एक सरणी बनाएं।

1

तो फिर ए में अपनी एफ की बजाय कॉलर की सरणी को संशोधित करने में एफ कैसे है?

इसकी अपनी प्रति नहीं है। इसमें कॉलर की सरणी का संदर्भ है।

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