2009-07-14 20 views
5

मैं रनटाइम पर प्रतिबिंब का उपयोग करके संग्रह का सामान्य प्रकार प्राप्त करना चाहता हूं।रनटाइम पर सामान्य संग्रह प्रकार परम निर्दिष्ट करना (जावा प्रतिबिंब)

संहिता (जावा):

Field collectionObject = object.getClass().getDeclaredField(
    collectionField.getName()); 
//here I compare to see if a collection 
if (Collection.class.isAssignableFrom(collectionObject.getType())) { 
    // here I have to use the generic type of the collection 
    // to see if it's from a specific type - in this case Persistable 
    if (Persistable.class.isAssignableFrom(GENERIC_TYPE_COLLECTION.class)) { 
    } 
} 

वहाँ कार्यावधि में जावा में संग्रह के सामान्य प्रकार होने का कोई तरीका है? मेरे मामले में मुझे संग्रह के जेनेरिक प्रकार के क्लास की आवश्यकता है।

अग्रिम धन्यवाद!

+0

मुझे इसी तरह की समस्या का सामना करना पड़ रहा था और अंत में यह मेरे लिए हल हो गया: http://stackoverflow.com/a/183232/639119 – Zds

उत्तर

17

Type erasure का अर्थ है कि ऑब्जेक्ट सामान्य प्रकार के बारे में जानकारी निष्पादन समय पर मौजूद नहीं है।

(लिंक एंजेलिका लैंगर के Java Generics FAQ के प्रासंगिक अनुभाग जो लगभग हर सवाल आप संभवतः जावा जेनरिक :)

हालांकि के बारे में पूछ सकते हैं, तो आप वास्तव में एक वस्तु के प्रकार में कोई दिलचस्पी नहीं कर रहे हैं उत्तर देना चाहिए करने के लिए है - आप फ़ील्ड के प्रकार में रूचि रखते हैं। मैंने सवाल को गलत तरीके से पढ़ा है, और हालांकि जवाब स्वीकार कर लिया गया है, मुझे उम्मीद है कि इसे अब ठीक करके संशोधित करना होगा :)

यदि फ़ील्ड एक प्रकार पैरामीटर का उपयोग नहीं करता है, तो यह किया जा सकता है। उदाहरण के लिए:

import java.lang.reflect.*; 
import java.util.*; 

public class Test 
{ 
    public List<String> names; 

    public static void main(String [] args) 
     throws Exception // Just for simplicity! 
    { 
     Field field = Test.class.getDeclaredField("names"); 

     ParameterizedType type = (ParameterizedType) field.getGenericType(); 

     // List 
     System.out.println(type.getRawType()); 

     // Just String in this case 
     for (Type typeArgument : type.getActualTypeArguments()) 
     { 
      System.out.println(" " + typeArgument); 
     } 
    } 
} 

तो क्षेत्र क्षेत्र में किया जा रहा List<T> के साथ एक कक्षा T में थे तो आप संग्रह के लिए प्रकार तर्क पता करने के लिए में उदाहरण के लिए प्रकार तर्क पता करने के लिए होगा।

इसे अपने आवश्यक कोड में अनुवाद करना कुछ हद तक मुश्किल है - आपको संग्रह वर्ग के बिंदु पर टाइप तर्क को वास्तव में जानने की आवश्यकता है। उदाहरण के लिए, अगर किसी ने घोषणा की:

public class StringCollection implements Collection<String> 

और फिर प्रकार StringCollection के एक क्षेत्र, उस क्षेत्र में ही किसी भी प्रकार के तर्क नहीं होता था। इसके बाद आपको getGenericSuperType और getGenericInterfaces को तब तक जांचना होगा जब तक आप जो चाहते थे उसे प्राप्त न करें।

यह वास्तव में ऐसा करना आसान नहीं होगा, भले ही यह संभव हो। अगर मैं आप थे तो मैं आपके डिजाइन को बदलने की कोशिश करता हूं ताकि आपको इसकी आवश्यकता न हो।

+1

रिकर्सिव जांच वास्तव में आसान नहीं है, खाते में कई कोने के मामले हैं। और यह सिर्फ पहला कदम है, इसके बाद आपको एक आश्वस्त करने की आवश्यकता है समकक्ष से जो जेनरिक को भी संभालता है। मैं इसे स्वयं लागू करने की कोशिश करने की सिफारिश नहीं करता। मैंने एक पुस्तकालय लिखा जो आपके लिए यह करता है, जिसे gentyref कहा जाता है। Http://code.google.com/p/gentyref/ देखें। –

0

आप उस वस्तु का सामान्य प्रकार प्राप्त कर सकते हैं जिसे आपने ऑब्जेक्ट को Field.getGenericType से पढ़ा है। ध्यान दें कि यह क्षेत्र एक कच्चा प्रकार हो सकता है, जेनेरिक लेकिन एक सामान्य तर्क जो कच्चा होता है), उदाहरण के प्रकार का उपयोग करें, वाइल्डकार्ड का उपयोग करें, आदि

0

मेरी पोस्ट से कॉपी किया गया: https://stackoverflow.com/questions/1004022/java-generic-class-determine-type/1005283#1005283

मैंने कुछ परियोजनाओं के लिए यहां बताए गए समान समाधान का उपयोग किया है और इसे बहुत उपयोगी पाया है।

http://blog.xebia.com/2009/02/07/acessing-generic-types-at-runtime-in-java/

यह की jist उपयोग कर रहा है कार्यावधि में प्रकार पैरामीटर निर्धारित करने के लिए निम्नलिखित:

public Class returnedClass { 
    ParameterizedType parameterizedType = 
    (ParameterizedType) getClass().getGenericSuperClass(); 
return (Class) parameterizedtype.getActualTypeArguments()[0]; 
} 
9

आप बिल्कुल आप क्या चाहते हैं कर सकते हैं।टाइप एरर का मतलब है कि आप अपने सामान्य प्रकार के संग्रह के इंस्टेंस का निरीक्षण नहीं कर सकते हैं, लेकिन आप निश्चित रूप से इसके सामान्य प्रकार के लिए फ़ील्ड का निरीक्षण कर सकते हैं।

class Thing { 
    List<Persistable> foo; 
} 


Field f = Thing.class.getDeclaredField("foo"); 
if(Collection.class.isAssignableFrom(f.getType()) { 
    Type t = f.getGenericType(); 
    if(t instanceof ParameterizedType) { 
    Class genericType = (Class)((ParameterizedType)t).getActualTypeArguments()[0]; 
    if(Persistable.class.isAssignableFrom(genericType)) 
     return true; 
    } 
} 

बातें अगर आप

Class Thing<T> { 
    List<T> foo; 
} 

है तो ऊपर काम नहीं करेगा जो गलत यहां जा सकते हैं, उदाहरण के लिए, का एक बहुत कुछ नहीं है।

+1

मैं इस लाइन का अनुमान लगा रहा हूं: कक्षा जेनेरिक टाइप = (कक्षा) ((पैरामीटरेट टाइप) टी) .getActualTypeArguments [0]; कक्षा जेनेरिक टाइप = (कक्षा) ((पैरामीटरेट टाइप) टी) .getActualTypeArguments() [0]; ? – andersonbd1

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