Phản ánh Java nhận tất cả các trường riêng tư


76

Tôi tự hỏi có cách nào để lấy tất cả các trường riêng của một số lớp trong java và kiểu của chúng không.

Ví dụ, giả sử tôi có một lớp học

class SomeClass {
    private String aaa;
    private SomeOtherClass bbb;
    private double ccc;
}

Bây giờ tôi muốn có được tất cả các lĩnh vực tư nhân ( aaa, bbb, ccc) của lớp SomeClass(Mà không biết tên của tất cả các lĩnh vực trả trước) và kiểm tra kiểu của chúng.


7
@atk Không ai bắt bạn trả lời; nhưng đối với nhiều người trong số chúng ta đặt câu hỏi này từ Google, câu trả lời hàng đầu là một lời giải thích ngắn gọn hơn nhiều so với việc đọc qua các bài viết dài về sự suy ngẫm. Ngay cả những câu hỏi dài như thế này cũng góp phần tạo nên SO ngày nay.
Angad

Câu trả lời:


124

Có thể lấy tất cả các trường bằng phương thức getDeclaredFields()của Class. Sau đó, bạn phải kiểm tra công cụ sửa đổi của từng trường để tìm những trường riêng tư:

List<Field> privateFields = new ArrayList<>();
Field[] allFields = SomeClass.class.getDeclaredFields();
for (Field field : allFields) {
    if (Modifier.isPrivate(field.getModifiers())) {
        privateFields.add(field);
    }
}

Lưu ý rằng getDeclaredFields() sẽ không trả về các trường kế thừa.

Cuối cùng, bạn nhận được loại trường với phương thức Field.getType () .


Tôi nghĩ rằng thực tế là tôi đang làm việc với một lớp học biên soạn làm cho nó khá bất tiện vì các lĩnh vực quay trở lại có những cái tên như m0, m1, vv, và là loại java.lang.reflect.Method. Điều này có thể là do tôi cố gắng sử dụng phản chiếu trên Spring Bean được truyền vào một giao diện?
payne

13

Bạn có thể sử dụng Modifierđể xác định xem một trường là riêng tư. Hãy chắc chắn sử dụng getDeclaredFieldsphương thức để đảm bảo rằng bạn truy xuất các trường riêng tư từ lớp, việc gọi getFieldssẽ chỉ trả về các trường công khai.

public class SomeClass {

    private String aaa;
    private Date date;
    private double ccc;
    public int notPrivate;

    public static void main(String[] args) {
        List<Field> fields = getPrivateFields(SomeClass.class);
        for(Field field: fields){
            System.out.println(field.getName());
        }
    }

    public static List<Field> getPrivateFields(Class<?> theClass){
        List<Field> privateFields = new ArrayList<Field>();

        Field[] fields = theClass.getDeclaredFields();

        for(Field field:fields){
            if(Modifier.isPrivate(field.getModifiers())){
                privateFields.add(field);
            }
        }
        return privateFields;
    }
}

2
@AfzaalAhmadZeeshan tại sao bạn thay đổi chỉnh sửa của tôi "clazz" thành "lớp học", khi chúng ta rõ ràng cần phải sử dụng biến "clazz" và không phải là "lớp học" từ khóa
vallentin

Tôi xin lỗi vì sai lầm đó, tôi nghĩ rằng đây là một sai lầm vì không có biến nào được gắn với tài liệu hoặc mã ở bất kỳ đâu! Xin lỗi tôi vì điều đó ..
Afzaal Ahmad Zeeshan

3
@AfzaalAhmadZeeshan có một biến, nó nằm trong các đối số của phương thức. Tuy nhiên, bạn có muốn thu hồi thay đổi của mình không, vì tôi không thể thay đổi nó.
vallentin


8

Sử dụng Java 8:

Field[] fields = String.class.getDeclaredFields();
List<Field> privateFieldList = Arrays.asList(fields).stream().filter(field -> Modifier.isPrivate(field.getModifiers())).collect(
        Collectors.toList());

7

Kiểm tra xem Trường có riêng tư không

Bạn có thể lọc các Trường bằng Modifier.isPrivate :

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
// ...
Field field = null;
// retrieve the field in some way
// ...
Modifier.isPrivate(field.getModifiers())

trên một Fieldđối tượng duy nhất trả về truenếu trườngprivate


Thu thập tất cả các Trường của một lớp

Để thu thập tất cả các Trường sử dụng:

1) Nếu bạn chỉ cần các trường của lớp mà không cần các trường lấy từ hệ thống phân cấp lớp, bạn có thể chỉ cần sử dụng:

Field[] fields = SomeClass.class.getDeclaredFields();

2) Nếu bạn không muốn phát minh lại bánh xe và nhận tất cả các trường của hệ thống phân cấp lớp, bạn có thể dựa vào 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));
    }
}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.