2009-06-25 42 views
91

Tôi đã là đối tượng Java 'ChildObj' được mở rộng từ 'ParentObj'. Bây giờ, nếu có thể truy xuất tất cả các tên thuộc tính và các giá trị của ChildObj, bao gồm cả các thuộc tính thừa kế, sử dụng cơ chế phản chiếu Java?Lấy các tên/giá trị thuộc tính được thừa hưởng bằng cách sử dụng Java Reflection

Class.getFields cung cấp cho tôi mảng thuộc tính công khai và Class.getDeclaredFields cung cấp cho tôi mảng của tất cả các trường, nhưng không có trường nào trong số đó bao gồm danh sách trường được kế thừa.

Có cách nào để truy lục các thuộc tính kế thừa không?

Trả lời

132

không, bạn cần tự viết. Đó là một phương pháp đơn giản đệ quy kêu gọi Class.getSuperClass():

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

vâng. nghĩ về điều đó. nhưng muốn kiểm tra xem có cách nào khác để làm điều đó không. cảm ơn. :) – Veera

+0

nó hoạt động. cảm ơn. – Veera

+6

Vượt qua một đối số có thể thay đổi và trả về nó có lẽ không phải là một thiết kế tuyệt vời. fields.addAll (type.getDeclaredFields()); sẽ được thông thường hơn một vòng lặp tăng cường với thêm. –

5

Bạn cần phải gọi:

Class.getSuperclass().getDeclaredFields() 

recursing lên hệ thống phân cấp thừa kế khi cần thiết.

1

Bạn có thể thử:

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

Đây là giải pháp ưa thích của tôi, tuy nhiên tôi sẽ gọi nó là "getAllFields" vì nó trả về các trường của lớp đã cho. – Pino

+0

Tôi đồng ý với Pino – Marquez

+3

Mặc dù tôi thích rất nhiều đệ quy (thật thú vị!), Tôi thích khả năng đọc của phương thức này và các tham số trực quan hơn (không yêu cầu một bộ sưu tập mới để vượt qua), không còn nếu (ẩn trong mệnh đề for) và không lặp lại trên các trường. –

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

phiên bản của "DidYouMeanThatTomHa ..." giải pháp trên

3

Các giải pháp đệ quy là OK Làm việc, vấn đề duy nhất là nhỏ rằng họ trả lại một superset của các thành viên được thừa nhận và thừa hưởng. Lưu ý rằng phương thức getDeclaredFields() cũng trả về các phương thức riêng. Vì vậy, khi bạn điều hướng toàn bộ phân cấp của lớp cha, bạn sẽ bao gồm tất cả các trường riêng được khai báo trong các lớp bậc trên và những trường không được kế thừa.

Bộ lọc đơn giản với công cụ sửa đổi.isPublic || vị Modifier.isProtected sẽ làm gì:

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

Nếu thay vào đó bạn muốn dựa vào một thư viện để thực hiện điều này, Apache Commons Lang phiên bản 3.2+ cung cấp 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

Bùng nổ! Tôi yêu không sáng tạo lại bánh xe. Chúc mừng cho điều này. –

0

ngắn hơn và có ít đối tượng khởi tạo? ^^

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 không thể tìm thấy biểu tượng. –

+1

Lớp này là từ Apache Commons Lang. –

+0

Apache đã có một hàm FieldUtils.getAllFields để xử lý yêu cầu câu hỏi này. –

4

Sử dụng Reflections thư viện:

public Set<Field> getAllFields(Class<?> aClass) { 
    return org.reflections.ReflectionUtils.getAllFields(aClass); 
} 
Các vấn đề liên quan