परावर्तन जेनेरिक को फ़ील्ड मान मिलता है


132

मैं प्रतिबिंब के माध्यम से क्षेत्र मूल्य प्राप्त करने की कोशिश कर रहा हूं। समस्या यह है कि मुझे खेतों के प्रकार का पता नहीं है और मूल्य प्राप्त करते समय इसे तय करना होगा।

यह कोड इस अपवाद के साथ परिणाम देता है:

Java.lang.tring फ़ील्ड कॉम सेट नहीं कर सकता है .... फ़ील्ड नाम से java.lang.String

Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);

Class<?> targetType = field.getType();
Object objectValue = targetType.newInstance();

Object value = field.get(objectValue);

मैंने कास्ट करने की कोशिश की, लेकिन मुझे संकलन त्रुटियाँ मिलीं:

field.get((targetType)objectValue)

या

targetType objectValue = targetType.newInstance();

मैं यह कैसे कर सकता हूँ?


4
एपीआई को देखते हुए , तर्क field.get()होना चाहिए object, नहीं objectValue
akaIDIOT

जवाबों:


144

पहले उत्तर की तरह, आपको उपयोग करना चाहिए:

Object value = field.get(objectInstance);

एक और तरीका है, जिसे कभी-कभी पसंद किया जाता है, गेटर को गतिशील रूप से बुला रहा है। उदाहरण कोड:

public static Object runGetter(Field field, BaseValidationObject o)
{
    // MZ: Find the correct method
    for (Method method : o.getMethods())
    {
        if ((method.getName().startsWith("get")) && (method.getName().length() == (field.getName().length() + 3)))
        {
            if (method.getName().toLowerCase().endsWith(field.getName().toLowerCase()))
            {
                // MZ: Method found, run it
                try
                {
                    return method.invoke(o);
                }
                catch (IllegalAccessException e)
                {
                    Logger.fatal("Could not determine method: " + method.getName());
                }
                catch (InvocationTargetException e)
                {
                    Logger.fatal("Could not determine method: " + method.getName());
                }

            }
        }
    }


    return null;
}

यह भी ध्यान रखें कि जब आपकी कक्षा किसी अन्य वर्ग से विरासत में मिलती है, तो आपको फ़ील्ड को फिर से निर्धारित करने की आवश्यकता होती है। उदाहरण के लिए, किसी दिए गए वर्ग के सभी फ़ील्ड प्राप्त करना;

    for (Class<?> c = someClass; c != null; c = c.getSuperclass())
    {
        Field[] fields = c.getDeclaredFields();
        for (Field classField : fields)
        {
            result.add(classField);
        }
    }

1
यह बिल्कुल सच नहीं है कि आपको अपने आप को सुपर क्लास के माध्यम से पुनरावृत्त करने की आवश्यकता है। C.getFields () या c.getField () स्वचालित रूप से प्रत्येक क्रियान्वयन इंटरफ़ेस पर और सभी सुपरक्लेसेस के माध्यम से पुनरावर्ती रूप से फ़ील्ड खोजेगा। तो बस getDeclaredX से getX पर स्विच करने के लिए पर्याप्त है।
प्रेज़ेमीस्लाव ńadyński

3
वास्तव में, getFields () दिनचर्या आपको सभी सुपर वर्गों और इंटरफेस के लिए खेतों को लाने की अनुमति देगा, लेकिन केवल सार्वजनिक वाले। आमतौर पर, खेतों को निजी / संरक्षित किया जाता है और गेटर्स / सेटर के माध्यम से उजागर किया जाता है।
Marius

@ मेरी, क्या मुझे पता है कि पैकेज क्या है BaseValidationObject?
रंडितान

मेरे निजी कोड रिपॉजिटरी में निहित @Randytan, आप इसे ऑब्जेक्ट से बदल सकते हैं। स्थैतिक लकड़हारा कॉल पर भी यही बात लागू होती है, उन्हें अपने लकड़हारे (उदाहरण) से बदल दें।
मारियस

@ objectवर्ग में विधि नहीं है getMethods()। कोई सलाह?
रंडितान

127

आपको फ़ील्ड की विधि प्राप्त करने के लिए ऑब्जेक्ट पास करना चाहिए , इसलिए

  Field field = object.getClass().getDeclaredField(fieldName);    
  field.setAccessible(true);
  Object value = field.get(object);

6
क्या आपको पता है कि फ़ील्ड में ऑब्जेक्ट का उपयोग क्यों किया जाता है। ऑब्जेक्ट (ऑब्जेक्ट) - फ़ील्ड स्वयं उस ऑब्जेक्ट से आता है, इसे फिर से आवश्यकता क्यों है!
सर्प

18
@serup नहीं, फ़ील्ड ऑब्जेक्ट क्लास ऑब्जेक्ट से आता है, जिसका आपके वास्तविक उदाहरण के साथ कोई संबंध नहीं है। ( object.getClass()आपको यह क्लास ऑब्जेक्ट लौटा देगा)
दिमित्री स्पिकाल्स्की

1
objectस्निपेट में परिभाषित नहीं है इसलिए पाठकों को यह समझ नहीं आ रहा है कि इसका उपयोग कैसे किया जाए।
गिलीटरस

उस स्थिति में @ गिल्टर, वे अभी तक प्रतिबिंब का उपयोग नहीं करते हैं और पहले कुछ बुनियादी कौशल प्राप्त करते हैं। परावर्तन एक उन्नत पर्याप्त विषय है जो यह नहीं समझाता है कि एक चर का objectमतलब है हमारा लक्ष्य वस्तु / उदाहरण जिसके साथ हम काम करते हैं। मुझे लगता है कि पाठक वास्तव objectमें इस उत्तर में क्या है के साथ पूरी तरह से ठीक हैं ।
दिमित्री स्पिकाल्स्की

@ रजनप्रसाद वास्तव में नहीं। प्रश्न में एक ही वस्तु है जिसका एक नाम 'वस्तु' है। अन्य वस्तुओं के अन्य नाम हैं। उत्तर सटीक और प्रश्नों के अनुरूप और उन नामों के लिए है जिनका उपयोग प्रश्न में यथासंभव स्पष्ट करने के लिए किया जाता है। यदि यह आपके लिए काम नहीं करता है - मुझे नहीं पता कि इसे कैसे और अधिक स्पष्ट किया जाए और आपको अन्य उत्तरों की कोशिश करनी चाहिए या शायद अभी तक प्रतिबिंब से बचें।
दिमित्री स्पिकाल्स्की

19

मैं कक्षा के सदस्यों और मूल्यों (सरल और त्वरित डिबगिंग) को देखने के लिए अपनी वरीयता वर्ग के कार्यान्वयन में () के कार्यान्वयन में प्रतिबिंब का उपयोग करता हूं।

मैं उपयोग कर रहा सरलीकृत कोड:

@Override
public String toString() {
    StringBuilder sb = new StringBuilder();

    Class<?> thisClass = null;
    try {
        thisClass = Class.forName(this.getClass().getName());

        Field[] aClassFields = thisClass.getDeclaredFields();
        sb.append(this.getClass().getSimpleName() + " [ ");
        for(Field f : aClassFields){
            String fName = f.getName();
            sb.append("(" + f.getType() + ") " + fName + " = " + f.get(this) + ", ");
        }
        sb.append("]");
    } catch (Exception e) {
        e.printStackTrace();
    }

    return sb.toString();
}

मुझे उम्मीद है कि यह किसी की मदद करेगा, क्योंकि मैंने भी खोज की है।


12

यद्यपि यह वास्तव में मेरे लिए स्पष्ट नहीं है कि आप क्या हासिल करने की कोशिश कर रहे हैं, मुझे आपके कोड में एक स्पष्ट त्रुटि दिखाई दी: Field.get()उस ऑब्जेक्ट की अपेक्षा करता है जिसमें फ़ील्ड तर्क के रूप में है, उस फ़ील्ड के कुछ (संभव) मान नहीं। तो आपके पास होना चाहिए field.get(object)

जब से आप फ़ील्ड मान की तलाश करते दिखाई देते हैं, आप इसे निम्न प्रकार से प्राप्त कर सकते हैं:

Object objectValue = field.get(object);

फ़ील्ड प्रकार को तत्काल करने और कुछ खाली / डिफ़ॉल्ट मान बनाने की आवश्यकता नहीं है; या शायद वहाँ कुछ है जो मुझे याद किया।


2
objectपरिभाषित नहीं है, पाठकों को समझ नहीं आ रहा है कि उत्तर कैसे लागू किया जाए।
गिलीटरस

10
 Integer typeValue = 0;
 try {
     Class<Types> types = Types.class;
     java.lang.reflect.Field field = types.getDeclaredField("Type");
     field.setAccessible(true);
     Object value = field.get(types);
     typeValue = (Integer) value;
 } catch (Exception e) {
     e.printStackTrace();
 }

4

आप गलत तर्क के साथ कॉल कर रहे हैं।

यह होना चाहिए:

Object value = field.get(object);

2
objectपरिभाषित नहीं किया गया है, पाठकों को यह समझ नहीं आ रहा है कि उत्तर में उदाहरण को कैसे लागू किया जाए
घिल्टरस

2

मैं कोटलिन में अपना समाधान पोस्ट करता हूं, लेकिन यह जावा वस्तुओं के साथ भी काम कर सकता है। मैं एक फ़ंक्शन एक्सटेंशन बनाता हूं ताकि कोई भी ऑब्जेक्ट इस फ़ंक्शन का उपयोग कर सके।

fun Any.iterateOverComponents() {

val fields = this.javaClass.declaredFields

fields.forEachIndexed { i, field ->

    fields[i].isAccessible = true
    // get value of the fields
    val value = fields[i].get(this)

    // print result
    Log.w("Msg", "Value of Field "
            + fields[i].name
            + " is " + value)
}}

इस वेबपेज पर एक नज़र डालें: https://www.geeksforgeeks.org/field-get-method-in-java-with-examples/


1
    ` 
//Here is the example I used for get the field name also the field value
//Hope This will help to someone
TestModel model = new TestModel ("MyDate", "MyTime", "OUT");
//Get All the fields of the class
 Field[] fields = model.getClass().getDeclaredFields();
//If the field is private make the field to accessible true
fields[0].setAccessible(true);
//Get the field name
  System.out.println(fields[0].getName());
//Get the field value
System.out.println(fields[0].get(model));
`
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.