प्रकार की सुरक्षा को संरक्षित करते समय आप जिस प्रकार की तलाश कर रहे हैं, उसका एक प्रकार प्राप्त करने के लिए जेनेरिक का उपयोग कैसे करें (जैसा कि अन्य उत्तरों के विपरीत है, जो या तो आपको एक 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रूप में कॉल करना । विधि कॉलिंग रिटर्न एक वस्तु सरणी के घटक प्रकार का प्रतिनिधित्व करने का प्रतिनिधित्व करती वस्तु जिस पर विधि बुलाया गया था (जैसे के लिए , यदि वस्तु एक सरणी का प्रतिनिधित्व नहीं करता है)।ObjectClassintgetComponentTypeClassClassString.classString[].classnullClass
यह अंतिम वाक्य पूरी तरह से सही नहीं है। कॉलिंग 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));
}