1) इंटरनेट पर और जेकिक्स और varargs के साथ विशेष मुद्दे के बारे में StackOverflow पर कई उदाहरण हैं। असल में, यह आप एक प्रकार पैरामीटर प्रकार के तर्कों के परिवर्तनशील है जब है:
void foo(T... args);
जावा में, varargs एक वाक्यात्मक चीनी कि संकलन समय पर एक सरल "फिर से लेखन" से होकर गुजरती है कर रहे हैं: एक varargs पैरामीटर X...
प्रकार X[]
के पैरामीटर में परिवर्तित किया गया है; और हर बार इस varargs विधि के लिए एक कॉल किया जाता है, संकलक varargs पैरामीटर में चला जाता है कि सभी "परिवर्तनीय तर्क" एकत्र करता है, और new X[] { ...(arguments go here)... }
की तरह एक सरणी बनाता है।
यह तब काम करता है जब varargs प्रकार String...
जैसा ठोस होता है। जब यह एक प्रकार परिवर्तनीय है जैसे T...
, यह तब भी काम करता है जब T
उस कॉल के लिए ठोस प्रकार के रूप में जाना जाता है। जैसे यदि उपर्युक्त विधि Foo<T>
वर्ग का हिस्सा थी, और आपके पास Foo<String>
संदर्भ है, तो foo
पर कॉल करना ठीक होगा क्योंकि हम जानते हैं कि T
String
कोड में उस बिंदु पर है।
हालांकि, यह काम नहीं करता है जब T
का "मान" एक और प्रकार पैरामीटर है। जावा में, टाइप-पैरामीटर घटक प्रकार (new T[] { ... }
) की सरणी बनाना असंभव है। तो जावा new Object[] { ... }
का उपयोग करता है (यहां Object
T
की ऊपरी सीमा है; यदि ऊपरी सीमा कुछ अलग थी, तो यह Object
के बजाय होगा, और फिर आपको एक कंपाइलर चेतावनी देता है।
तो new T[]
के बजाय new Object[]
बनाने के साथ क्या गलत है? खैर, जावा में सरणी रनटाइम पर उनके घटक प्रकार को जानते हैं। इस प्रकार, पास किए गए सरणी ऑब्जेक्ट में रनटाइम पर गलत घटक प्रकार होगा।
शायद varargs का सबसे आम उपयोग के लिए, बस तत्वों से अधिक पुनरावृति करने के लिए, यह कोई समस्या (आप सरणी के क्रम प्रकार के बारे में परवाह नहीं है) है, इसलिए इस सुरक्षित है:
@SafeVarargs
final void foo(T... args) {
for (T x : args) {
// do stuff with x
}
}
हालांकि, किसी भी चीज के लिए जो पारित सरणी के रनटाइम घटक प्रकार पर निर्भर करता है, यह सुरक्षित नहीं होगा।
class UnSafeVarargs
{
static <T> T[] asArray(T... args) {
return args;
}
static <T> T[] arrayOfTwo(T a, T b) {
return asArray(a, b);
}
public static void main(String[] args) {
String[] bar = arrayOfTwo("hi", "mom");
}
}
समस्या यहाँ है कि हम आदेश T[]
के रूप में यह वापस जाने के लिए में T[]
होने की args
के प्रकार पर निर्भर है: यहाँ कुछ है कि असुरक्षित है और दुर्घटनाओं का एक सरल उदाहरण है। लेकिन वास्तव में रनटाइम पर तर्क का प्रकार T[]
का उदाहरण नहीं है।
3) अपने विधि प्रकार T...
(जहां टी किसी भी प्रकार के पैरामीटर है की एक तर्क है), तो:
- सुरक्षित: अपने विधि केवल तथ्य पर निर्भर करता है कि सरणी के तत्वों के उदाहरण हैं
T
- असुरक्षित की: प्रकारके रूप में यह लौटने: यह तथ्य यह है कि सरणी
T[]
चीज़ें है कि सरणी के क्रम प्रकार पर निर्भर शामिल का एक उदाहरण है पर निर्भर करता है, प्रकार T[]
की एक पैरामीटर के लिए एक तर्क के रूप में यह पारित, .getClass()
का उपयोग कर सरणी प्रकार हो रही है यह तरीकों कि सरणी, List.toArray()
और Arrays.copyOf()
तरह के रनटाइम प्रकार पर निर्भर करने के लिए पारित करने, आदि
2) भेद मैंने ऊपर वर्णित किया है कि स्वचालित रूप से आसानी से विशिष्ट होने के लिए बहुत जटिल है।
क्या आपने [जावाडॉक] (http://docs.oracle.com/javase/7/docs/api/java/lang/SafeVarargs.html) में उदाहरण (और स्पष्टीकरण) देखा है? – jlordo
आपके तीसरे प्रश्न के लिए, एक अभ्यास हमेशा पहले तत्व और दूसरों के लिए होता है: 'myTethod को पुनः टाइप करें (Arg पहले, Arg ... अन्य) '। यदि आप 'पहले' निर्दिष्ट नहीं करते हैं, तो खाली सरणी की अनुमति है, और आपके पास एक ही नाम से एक ही विधि के साथ एक विधि हो सकती है, जिसमें कोई तर्क नहीं होता है, जिसका अर्थ है कि जेवीएम को यह निर्धारित करने में कठिनाई होगी कि कौन सी विधि होनी चाहिए बुलाया। – fge
@jlordo मैंने किया, लेकिन मुझे समझ में नहीं आ रहा है कि यह varargs संदर्भ में क्यों दिया गया है, क्योंकि यह इस स्थिति को एक varargs फ़ंक्शन के बाहर आसानी से समाप्त कर सकता है (सत्यापित किया गया है, अपेक्षित प्रकार की सुरक्षा चेतावनियों और रनटाइम पर त्रुटियों के साथ संकलित) .. – Oren