«Generic array creation» — वह एरर जो हर Java डेवलपर को परेशान करती है
\n\nक्या आपने कभी new T[10] लिखा और कम्पाइलर से लाल निशान पाया? अगर हाँ, तो आप अकेले नहीं हैं। Stack Overflow पर सवाल «How can I create a generic array in Java?» को लाखों बार देखा जा चुका है। यह कोई संयोग नहीं: Java में generic array बनाना उन विषयों में से एक है जहाँ थ्योरी और प्रैक्टिस में अंतर होता है, और IDE आपकी बात समझने से इनकार कर देता है।
इस लेख में हम जानेंगे कि Java generic arrays को क्यों रोकता है, टाइप सेफ्टी खोए बिना इस सीमा को कैसे पार करें, और कब array ArrayList से बेहतर है। चलिए शुरू करते हैं!
new T[10] क्यों काम नहीं करता? असली वजह — Type Erasure
\n\nयह समझने के लिए कि Java में generic array कैसे बनाएं, पहले यह जानना ज़रूरी है कि कम्पाइलर क्यों चिल्लाता है। इसकी वजह है type erasure (टाइप इरेज़र)। Java में जेनेरिक्स सिर्फ कम्पाइल टाइम पर मौजूद होते हैं। रनटाइम पर T की जानकारी मिट जाती है और उसकी जगह Object (या बाउंड्री) आ जाती है।
जबकि Java में arrays reifiable टाइप होते हैं — वे रनटाइम पर अपने कम्पोनेंट टाइप को जानते हैं। इसलिए JVM चेक कर सकता है कि array में सिर्फ सही टाइप के एलिमेंट डाले जाएं। अगर आप new T[10] लिख पाते, तो रनटाइम पर array Object[] होता, और आप उसमें String, Integer और Date एक साथ डाल सकते — जो टाइप सेफ्टी की पूरी अवधारणा को तोड़ता है।
यही कारण है कि कम्पाइलर यह एरर देता है:
\n// ❌ कम्पाइल एरर: generic array creation\npublic class Box<T> {\n private T[] array = new T[10]; // Cannot create a generic array of T\n}\n\nतरीका 1: सबसे आसान — ArrayList का उपयोग करें
\n\nअक्सर आपको array की ज़रूरत ही नहीं होती। ArrayList अंदरूनी रूप से Object[] के साथ काम करता है, लेकिन टाइप-सेफ इंटरफ़ेस प्रदान करता है। यह आदर्श समाधान है अगर आप नैनोसेकंड स्तर की परफॉरमेंस पर ध्यान नहीं दे रहे।
import java.util.ArrayList;\nimport java.util.List;\n\npublic class GenericListExample<T> {\n private List<T> list = new ArrayList<>();\n\n public void add(T item) {\n list.add(item);\n }\n\n public T get(int index) {\n return list.get(index);\n }\n\n public int size() {\n return list.size();\n }\n}\n\nफायदे: पूर्ण टाइप सेफ्टी, कोई चेतावनी नहीं, डायनामिक एक्सपैंशन सपोर्ट।
\nनुकसान: प्रिमिटिव के लिए बॉक्सिंग/अनबॉक्सिंग का छोटा ओवरहेड (लेकिन 99% ऐप्स के लिए यह ध्यान देने योग्य नहीं)।
तरीका 2: क्लासिक हैक — (T[]) new Object[size]
\n\nअगर आपको वास्तव में array चाहिए (जैसे परफॉरमेंस या लीगेसी API के साथ संगतता के लिए), तो टाइप कास्टिंग का उपयोग कर सकते हैं। यह सुरक्षित है अगर आप गारंटी देते हैं कि array आपकी क्लास की सीमा से बाहर नहीं जाएगा।
\n\npublic class Stack<T> {\n private T[] elements;\n private int size = 0;\n private static final int DEFAULT_CAPACITY = 10;\n\n @SuppressWarnings("unchecked")\n public Stack() {\n elements = (T[]) new Object[DEFAULT_CAPACITY];\n }\n\n public void push(T item) {\n if (size == elements.length) {\n resize();\n }\n elements[size++] = item;\n }\n\n public T pop() {\n if (size == 0) {\n throw new EmptyStackException();\n }\n T result = elements[--size];\n elements[size] = null; // GC की मदद करता है\n return result;\n }\n\n private void resize() {\n elements = Arrays.copyOf(elements, elements.length * 2);\n }\n}\n\nमहत्वपूर्ण: @SuppressWarnings("unchecked") एनोटेशन का उपयोग करना न भूलें। यह कम्पाइलर की चेतावनी को दबाता है, लेकिन आपको यह सुनिश्चित करना होगा कि आप array में केवल T टाइप के एलिमेंट ही डाल रहे हैं।