2009-06-25 33 views
91

का उपयोग करके विरासत विशेषता नाम/मानों को पुनर्प्राप्त करना मेरे पास जावा ऑब्जेक्ट 'ChildObj' है जिसे 'पेरेंटऑबज' से बढ़ाया गया है। अब, यदि जावा प्रतिबिंब तंत्र का उपयोग करके विरासत विशेषताओं समेत, ChildObj के सभी विशेषता नामों और मानों को पुनर्प्राप्त करना संभव है?जावा प्रतिबिंब

Class.getFields मुझे सार्वजनिक विशेषताओं की सरणी देता है, और Class.getDeclaredFields मुझे सभी फ़ील्ड की सरणी देता है, लेकिन उनमें से कोई भी विरासत फ़ील्ड सूची शामिल नहीं करता है।

विरासत विशेषताओं को पुनर्प्राप्त करने का कोई तरीका है?

उत्तर

132

नहीं, आपको इसे स्वयं लिखना होगा।

public static List<Field> getAllFields(List<Field> fields, Class<?> type) { 
    fields.addAll(Arrays.asList(type.getDeclaredFields())); 

    if (type.getSuperclass() != null) { 
     getAllFields(fields, type.getSuperclass()); 
    } 

    return fields; 
} 

@Test 
public void getLinkedListFields() { 
    System.out.println(getAllFields(new LinkedList<Field>(), LinkedList.class)); 
} 
+1

हाँ। इसके बारे में सोचा। लेकिन यह जांचना चाहता था कि ऐसा करने का कोई और तरीका है या नहीं। धन्यवाद। :) – Veera

+0

यह काम किया। धन्यवाद। – Veera

+6

एक म्यूटेबल तर्क पास करना और इसे वापस करना संभवतः एक महान डिज़ाइन नहीं है। fields.addAll (type.getDeclaredFields()); जोड़ने के साथ लूप के लिए बढ़ाया से अधिक पारंपरिक होगा। –

5

आप कॉल करने की आवश्यकता:

Class.getSuperclass().getDeclaredFields() 

वंशानुगत पदानुक्रम अप recursing आवश्यक के रूप में यह एक सरल पुनरावर्ती विधि Class.getSuperClass() पर कहा जाता है।

1

आप कोशिश कर सकते हैं:

Class parentClass = getClass().getSuperclass(); 
    if (parentClass != null) { 
     parentClass.getDeclaredFields(); 
    } 
0
private static void addDeclaredAndInheritedFields(Class c, Collection<Field> fields) { 
    fields.addAll(Arrays.asList(c.getDeclaredFields())); 
    Class superClass = c.getSuperclass(); 
    if (superClass != null) { 
     addDeclaredAndInheritedFields(superClass, fields); 
    } 
} 
71
public static List<Field> getAllFields(Class<?> type) { 
     List<Field> fields = new ArrayList<Field>(); 
     for (Class<?> c = type; c != null; c = c.getSuperclass()) { 
      fields.addAll(Arrays.asList(c.getDeclaredFields())); 
     } 
     return fields; 
    } 
+9

यह मेरा पसंदीदा समाधान है, हालांकि मैं इसे "getAllFields" कहूंगा क्योंकि यह दिए गए वर्ग के फ़ील्ड भी देता है। – Pino

+0

मैं पिनो – Marquez

+3

से सहमत हूं हालांकि मुझे बहुत अधिक रिकर्सिविटी पसंद है (यह मजेदार है!), मैं इस विधि की पठनीयता और अधिक सहज ज्ञान युक्त पैरामीटर (पास करने के लिए एक नया संग्रह की आवश्यकता नहीं है), और नहीं (खंड के लिए अंतर्निहित) और फ़ील्ड पर कोई पुनरावृत्ति नहीं है। –

2
private static void addDeclaredAndInheritedFields(Class<?> c, Collection<Field> fields) { 
    fields.addAll(Arrays.asList(c.getDeclaredFields())); 
    Class<?> superClass = c.getSuperclass(); 
    if (superClass != null) { 
     addDeclaredAndInheritedFields(superClass, fields); 
    }  
} 

कार्य "DidYouMeanThatTomHa ..." ऊपर

3

पुनरावर्ती समाधान ठीक हैं समाधान के संस्करण, केवल छोटे मुद्दा है कि वे घोषित और विरासत सदस्यों के सुपरसैट लौटते हैं। ध्यान दें कि getDeclaredFields() विधि निजी विधियों को भी लौटाती है। इसलिए दिया गया है कि आप पूरे सुपरक्लास श्रेणीबद्धता पर नेविगेट करते हैं, जिसमें सुपरक्लास में घोषित सभी निजी फ़ील्ड शामिल होंगे, और उन्हें विरासत में नहीं मिला है।

एक Modifier.isPublic के साथ एक साधारण फ़िल्टर || Modifier.isProtected विधेय करना होगा:

import static java.lang.reflect.Modifier.isPublic; 
import static java.lang.reflect.Modifier.isProtected; 

(...) 

List<Field> inheritableFields = new ArrayList<Field>(); 
for (Field field : type.getDeclaredFields()) { 
    if (isProtected(field.getModifiers()) || isPublic(field.getModifiers())) { 
     inheritableFields.add(field); 
    } 
} 
25

आप किसी लाइब्रेरी पर भरोसा करने के लिए पूरा करने के लिए इस, Apache Commons Lang संस्करण 3.2+ FieldUtils.getAllFieldsList प्रदान करता है चाहता था, तो इसके स्थान:

import java.lang.reflect.Field; 
import java.util.AbstractCollection; 
import java.util.AbstractList; 
import java.util.AbstractSequentialList; 
import java.util.Arrays; 
import java.util.LinkedList; 
import java.util.List; 

import org.apache.commons.lang3.reflect.FieldUtils; 
import org.junit.Assert; 
import org.junit.Test; 

public class FieldUtilsTest { 

    @Test 
    public void testGetAllFieldsList() { 

     // Get all fields in this class and all of its parents 
     final List<Field> allFields = FieldUtils.getAllFieldsList(LinkedList.class); 

     // Get the fields form each individual class in the type's hierarchy 
     final List<Field> allFieldsClass = Arrays.asList(LinkedList.class.getFields()); 
     final List<Field> allFieldsParent = Arrays.asList(AbstractSequentialList.class.getFields()); 
     final List<Field> allFieldsParentsParent = Arrays.asList(AbstractList.class.getFields()); 
     final List<Field> allFieldsParentsParentsParent = Arrays.asList(AbstractCollection.class.getFields()); 

     // Test that `getAllFieldsList` did truly get all of the fields of the the class and all its parents 
     Assert.assertTrue(allFields.containsAll(allFieldsClass)); 
     Assert.assertTrue(allFields.containsAll(allFieldsParent)); 
     Assert.assertTrue(allFields.containsAll(allFieldsParentsParent)); 
     Assert.assertTrue(allFields.containsAll(allFieldsParentsParentsParent)); 
    } 
} 
+3

बूम! मुझे पहिया को फिर से शुरू करने से प्यार नहीं है। इसके लिए चीयर्स। –

0

छोटी और कम वस्तु के साथ instantiated? ^^

private static Field[] getAllFields(Class<?> type) { 
    if (type.getSuperclass() != null) { 
     return (Field[]) ArrayUtils.addAll(getAllFields(type.getSuperclass()), type.getDeclaredFields()); 
    } 
    return type.getDeclaredFields(); 
} 
+0

HI @Alexis LEGROS: ArrayUtils प्रतीक नहीं मिल सकता है। –

+1

यह कक्षा अपाचे कॉमन्स लैंग से है। –

+0

अपाचे के पास इस प्रश्न अनुरोध को संभालने के लिए पहले से ही FieldUtils.getAllFields फ़ंक्शन है। –

4

उपयोग कुछ विचार पुस्तकालय:

public Set<Field> getAllFields(Class<?> aClass) { 
    return org.reflections.ReflectionUtils.getAllFields(aClass); 
} 
संबंधित मुद्दे