2009-06-25 27 views
91

ile devralınan öznitelik adlarını/değerlerini alma 'ParentObj'den genişletilmiş bir' ChildObj 'nesnesi var. Şimdi, Java yansıma mekanizmasını kullanarak, miras alınan nitelikler de dahil olmak üzere, ChildObj'nin tüm özellik isimlerini ve değerlerini almak mümkün mü?Java Yansıma

Class.getFields bana genel özellikler dizisini verir ve Class.getDeclaredFields bana tüm alanların dizisini verir, ancak bunların hiçbiri miras alınan alanlar listesini içermez.

Kalıtsal öznitelikleri de almanın bir yolu var mı?

cevap

132

Hayır, kendiniz yazmanız gerekiyor.

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

evet. bunun hakkında düşündüm. ama bunu yapmanın başka bir yolu olup olmadığını kontrol etmek istedim. Teşekkürler. :) – Veera

+0

çalıştı. Teşekkürler. – Veera

+6

Değişken bir argümana geçmek ve geri vermek büyük bir tasarım değildir. fields.addAll (type.getDeclaredFields()); Ekleme için geliştirilmiş bir döngüden daha geleneksel olurdu. –

5

Sen çağırmanız gerekir:

Class.getSuperclass().getDeclaredFields() 

gerektiği miras hiyerarşisini yukarı recursing Bu Class.getSuperClass() çağrısında basit tekrarlamalı bir yöntemdir.

1

Deneyebilirsin: "DidYouMeanThatTomHa ..." özyinelemeli çözümler Tamam

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

Bu benim tercih ettiğim çözümdür, ancak buna "getAllFields" diyebilirim çünkü verilen sınıfın alanlarını da döndürür. – Pino

+0

Pino – Marquez

+3

ile katılıyorum Çok fazla özyinelemeyi sevmeme rağmen (eğlenceli!), Ben bu yöntemin okunabilirliğini ve daha sezgisel parametreleri (geçmek için yeni bir koleksiyon gerekli değildir), daha fazla if (for cümlede) ve alanların üzerinde hiçbir yineleme yok. –

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); 
    }  
} 

, sadece küçük bir konudur beyan edilen ve devralınan üyelerin bir üst kümesini döndürdüğünü. GetDeclaredFields() yönteminin de özel yöntemler döndürdüğünü unutmayın. Tüm süper sınıf hiyerarşisinde gezinmeniz göz önüne alındığında, süper sınıflarda bildirilen tüm özel alanları içerecek ve bunlar devralınmayacaktır.

Modifier.isPublic ile basit bir süzgeç || Modifier.isProtected yüklem yapacağını:

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); 
    } 
} 
3

yukarıdaki çözüm sürümünü Çalışma

Class parentClass = getClass().getSuperclass(); 
    if (parentClass != null) { 
     parentClass.getDeclaredFields(); 
    } 
25

Bunu, Apache Commons Lang sürümü 3.2+ FieldUtils.getAllFieldsList sağlar gerçekleştirmek için bir kütüphane dayanmak istediğini yerine ise:

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

Bom! Direksiyonu yeniden icat etmeyi seviyorum. Bunun için alkışlar. –

0

Shorter ve daha az nesne ile örneklenen? ^^

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 sembolü bulamıyor. –

+1

Bu sınıf Apache Commons Lang'den. –

+0

Apache'nin bu soru isteğini işlemek için bir FieldUtils.getAllFields işlevi zaten var. –

4

Kullanım Yansımalar kitaplığı:

public Set<Field> getAllFields(Class<?> aClass) { 
    return org.reflections.ReflectionUtils.getAllFields(aClass); 
}