प्रकार की सुरक्षा को संरक्षित करते समय आप जिस प्रकार की तलाश कर रहे हैं, उसका एक प्रकार प्राप्त करने के लिए जेनेरिक का उपयोग कैसे करें (जैसा कि अन्य उत्तरों के विपरीत है, जो या तो आपको एक Object
सरणी देगा या संकलन समय पर चेतावनी में परिणाम देगा):
import java.lang.reflect.Array;
public class GenSet<E> {
private E[] a;
public GenSet(Class<E[]> clazz, int length) {
a = clazz.cast(Array.newInstance(clazz.getComponentType(), length));
}
public static void main(String[] args) {
GenSet<String> foo = new GenSet<String>(String[].class, 1);
String[] bar = foo.a;
foo.a[0] = "xyzzy";
String baz = foo.a[0];
}
}
यह चेतावनी के बिना संकलित करता है, और जैसा कि आप देख सकते हैं main
, जिस प्रकार के लिए आप एक उदाहरण की घोषणा करते हैं GenSet
, आप a
उस प्रकार के एक सरणी को असाइन कर सकते हैं , और आप a
उस प्रकार के एक चर से एक तत्व असाइन कर सकते हैं , जिसका अर्थ है कि सरणी और सरणी में मान सही प्रकार के हैं।
यह जावा ट्यूटोरियल में चर्चा के अनुसार रनटाइम टाइप टोकन के रूप में वर्ग शाब्दिक का उपयोग करके काम करता है । कक्षा शाब्दिकों को संकलक द्वारा उदाहरण के रूप में माना जाता है java.lang.Class
। एक का उपयोग करने के लिए, बस एक वर्ग के नाम का पालन करें .class
। इसलिए, कक्षा का प्रतिनिधित्व करने वाली String.class
एक Class
वस्तु के रूप में कार्य करता है String
। यह इंटरफेस, एनम, किसी भी आयामी सरणियों (जैसे String[].class
), आदिम (जैसे int.class
), और कीवर्ड void
(यानी void.class
) के लिए भी काम करता है ।
Class
खुद जेनेरिक (के रूप में घोषित है Class<T>
, जहां T
प्रकार है कि के लिए खड़ा Class
वस्तु का प्रतिनिधित्व किया जाता है), जिसका अर्थ है कि के प्रकार String.class
है Class<String>
।
इसलिए, जब भी आप कंस्ट्रक्टर को कॉल करते हैं, तो आप GenSet
पहले तर्क के लिए एक क्लास शाब्दिक में पास करते हैं, जो कि एरे GenSet
के घोषित प्रकार (उदाहरण के String[].class
लिए GenSet<String>
) के एक सरणी का प्रतिनिधित्व करता है । ध्यान दें कि आप प्राथमिकताओं का एक सरणी प्राप्त करने में सक्षम नहीं होंगे, क्योंकि टाइप चर के लिए आदिम का उपयोग नहीं किया जा सकता है।
कंस्ट्रक्टर के अंदर, विधि को कॉल करके cast
पास किए गए Object
तर्क को कक्षा में उस Class
ऑब्जेक्ट द्वारा प्रतिनिधित्व किया जाता है जिस पर विधि को बुलाया गया था। रिटर्न newInstance
में स्थिर विधि को ऑब्जेक्ट के द्वारा दर्शाए गए प्रकार के एक सरणी के रूप में पहले तर्क के रूप में और दूसरे तर्क के रूप में पारित लंबाई द्वारा निर्दिष्ट लंबाई के java.lang.reflect.Array
रूप में कॉल करना । विधि कॉलिंग रिटर्न एक वस्तु सरणी के घटक प्रकार का प्रतिनिधित्व करने का प्रतिनिधित्व करती वस्तु जिस पर विधि बुलाया गया था (जैसे के लिए , यदि वस्तु एक सरणी का प्रतिनिधित्व नहीं करता है)।Object
Class
int
getComponentType
Class
Class
String.class
String[].class
null
Class
यह अंतिम वाक्य पूरी तरह से सही नहीं है। कॉलिंग String[].class.getComponentType()
एक Class
वस्तु को वर्ग का प्रतिनिधित्व करता है String
, लेकिन इसका प्रकार है Class<?>
, ऐसा नहीं है Class<String>
, यही कारण है कि आप निम्न की तरह कुछ नहीं कर सकते।
String foo = String[].class.getComponentType().cast("bar"); // won't compile
उसी में प्रत्येक विधि के लिए Class
एक Class
वस्तु देता है ।
इस जवाब पर जोआचिम सॉयर की टिप्पणी के बारे में (मेरे पास इस पर टिप्पणी करने के लिए पर्याप्त प्रतिष्ठा नहीं है), उदाहरण के लिए कलाकारों का उपयोग T[]
एक चेतावनी के परिणामस्वरूप होगा क्योंकि कंपाइलर उस मामले में प्रकार की सुरक्षा की गारंटी नहीं दे सकता है।
इंगो की टिप्पणियों के बारे में संपादित करें:
public static <T> T[] newArray(Class<T[]> type, int size) {
return type.cast(Array.newInstance(type.getComponentType(), size));
}