2008-12-20 27 views
9

मान लीजिए मैं इस है:जावा में जेनेरिक सरणी का सबसे आसान विकल्प क्या है?

class test<T> 
{ 
    private T[] elements; 
    private int size; 
    public test(int size) 
    { 
     this.size = size; 
     elements = new T[this.size]; 
    } 
} 

ऐसा लगता है यह संभव है क्योंकि संकलक क्या निर्माता एक बार यह जेनरिक कोड या कुछ को बदलने के लिए कोशिश करता है कॉल करने के लिए पता नहीं है नहीं है। मैं क्या सोच रहा हूं, मैं यह करने के बारे में कैसे जाऊं? मुझे कल्पना है कि यह संभव है, यह देखते हुए कि यह सी ++ में कितनी आसानी से किया जाता है।

संपादित करें: क्षमा करें मैं तत्व घोषणाओं में [] भूल गया था।

उत्तर

0

मैं गलत हो सकता है, लेकिन अपने घोषणा अजीब लगता है, आप नहीं करना चाहिए था:

private T[] elements; 
13

समस्या यह है कि के बाद से सामान्य प्रकार पैरामीटर T संकलक द्वारा Object में तब्दील हो जाता है (यह प्रकार कहा जाता है मिटाएं), आप वास्तव में Object की एक सरणी बनाते हैं।

class test<T> 
{ 
    private T[] elements; 
    private int size; 
    public test(Class<T> type, int size) 
    { 
     this.size = size; 
     elements = (T[]) Array. newInstance(type, size); 
    } 
} 

आप यहाँ इसके बारे में एक बेहतर exlanation मिलेगा: Angelika Langer - Can I create an array whose component type is a type parameter?

8

एक सामान्य सरणी सबसे आसान विकल्प एक सूची का उपयोग करने के लिए है आप क्या कर सकते कार्य करने के लिए एक Class<T> प्रदान करना है।

+0

मैं सहमत हूं - कई कारणों से सूचियां आमतौर पर बेहतर विकल्प होती हैं। वास्तव में, कुछ लोग सुझाव देंगे कि जावा 5+ में एरे को भाषा का बहिष्कृत हिस्सा माना जाना चाहिए। मैं नहीं कह रहा हूं कि मैं उनमें से एक हूं ... लेकिन आपको वह राय मिल जाएगी। –

+0

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

2

दो समाधान हैं जिन्हें कक्षा वस्तु में गुजरने की आवश्यकता नहीं है। दोनों में मैं मान रहा हूं कि चूंकि यह एक निजी चर है, इसलिए आप एकमात्र व्यक्ति हैं जो चीजों को इसमें डालते हैं, और बाहरी दुनिया इसे नहीं देखती है।

एक केवल सादा ऑब्जेक्ट सरणी Object[] का उपयोग करना है। नुकसान यह है कि आप जेनेरिक के लाभ खो देंगे और आपको इससे बाहर आने वाली चीजें डालना होगा, जो कोड को उलझन में डाल देता है। लेकिन चूंकि आप एकमात्र व्यक्ति हैं जो चीजों को इसमें डालते हैं, तो कलाकार हमेशा सुरक्षित रहना चाहिए। बाहर जाने की आवश्यकता नहीं है कि क्या हो रहा है।

अन्य विकल्प एक हैक की तरह है। आप Object[] बनाते हैं, और उसके बाद इसे T[] पर "कास्ट करें"। तकनीकी रूप से यह अवैध है, क्योंकि Object[] और T[] विभिन्न रनटाइम प्रकार हैं और पूर्व को बाद में नहीं डाला जा सकता है। लेकिन जब तक आप कक्षा से बाहर सरणी पास नहीं करते हैं (उदा। इसे वापस या कुछ), तो इससे कोई समस्या नहीं आएगी, क्योंकि T[] किसी भी तरह Object[] पर मिटा दिया जाएगा, और वास्तव में कोई कलाकार नहीं किया जाता है। फिर आप आसानी से कोडिंग के लिए अपनी कक्षा में जेनेरिक के लाभ प्राप्त कर सकते हैं, लेकिन आपको बेहद सावधान रहना होगा कि उस सरणी को किसी भी व्यक्ति को पास न करें जो वास्तव में T[] की अपेक्षा करता है, क्योंकि यह नहीं है।

3

मैं बुनियादी सरणी से बचने के लिए और ArrayLists (या समान Lists) का उपयोग कारणों के समूह के लिए जहां भी संभव हो। दो सबसे महत्वपूर्ण हैं:

  1. मुझे गंजा सरणी के अर्थशास्त्र की आवश्यकता नहीं है। ब्रैकेट नोटेशन (यानी, पॉइंटर अंकगणितीय के लिए शॉर्टंड) के बारे में कुछ भी नहीं है जो मेरे जीवन को आसान बनाता है।

  2. यदि मैं सूचियों का उपयोग करता हूं, तो मैं आवश्यकतानुसार लाइन के नीचे अधिक परिष्कृत समवर्ती-सक्षम संरचनाओं का उपयोग करने के लिए स्वयं को स्थापित कर रहा हूं। उदाहरण के लिए, CopyOnWriteArrayList के साथ एक ArrayList को प्रतिस्थापित करना आसान है।

तो, अपने उदाहरण एक सामान्य ArrayList का उपयोग कर लिख कुछ इस तरह दिखेगा:

class test<T> { 
    /** It's not strictly necessary to make this a List vs. an ArrayList 
     You decide what interface you really need to expose internally. */ 
    private List<T> elements; 
    /** This parameter isn't necessary with a List. You can always call the 
     size() method instead. */ 
    private int size; 
    public test(int size) { 
     this.size = size; 
     elements = new ArrayList<T>(); 
     // Note that the next line isn't strictly necessary. 
     // An ArrayList can be dynamically resized without any real effort on your part. 
     elements.ensureCapacity(size); 
    } 
} 
0

आकार क्षेत्र बेमानी प्रकट होता है। आप आकार के बजाय तत्वों। लम्बाई हो सकता है।

class Test<T> { 
    private final T[] elements; 
    public test(int size) { 
     elements = (T[]) new Object[size]; 
    } 
} 

या आप टेस्ट क्लास को एक ऐरेलिस्ट के साथ बदल सकते हैं। यानी कक्षा को पूरी तरह से छोड़ दें।

+0

यह एक अपवाद फेंक देगा क्योंकि नई सरणी प्रकार टी [] नहीं है। – pdeva

+0

@pdeva: नहीं यह नहीं होगा; जब तक यह कक्षा परीक्षण के अंदर रहता है, यह किसी भी अपवाद को फेंक नहीं देगा क्योंकि टी [] का क्षरण ऑब्जेक्ट [] है; लेकिन आपको सावधान रहना होगा कि इसे कक्षा छोड़ने न दें – newacct

0

इस कोड को भी देखो:

public static <T> T[] toArray(final List<T> obj) { 
    if (obj == null || obj.isEmpty()) { 
     return null; 
    } 
    final T t = obj.get(0); 
    final T[] res = (T[]) Array.newInstance(t.getClass(), obj.size()); 
    for (int i = 0; i < obj.size(); i++) { 
     res[i] = obj.get(i); 
    } 
    return res; 
} 

यह एक ही प्रकार की एक सरणी के लिए वस्तु के किसी भी प्रकार की एक सूची बदल देता है।

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