Відбиття загальне значення поля отримання


132

Я намагаюся отримати значення поля через відображення. Проблема полягає в тому, що я не знаю тип полів і мушу вирішувати його, отримуючи значення.

Цей код виходить за винятком:

Неможливо встановити поле java.lang.String com .... fieldName до 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
Дивлячись на API , аргументом 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 () автоматично здійснюватиме пошук у полі кожного інтерфейсу реалізації та рекурсивно через усі суперкласи. Тому просто достатньо перейти на getX з getDeclaredX.
Перемислав Чадинський

3
Дійсно, програма getFields () дозволить отримати поля для всіх суперкласів та інтерфейсів, але лише для загальнодоступних. Зазвичай поля робляться приватними / захищеними та оголюються через геттери / сетери.
Маріус

@Marius, чи можу я знати, що таке пакет BaseValidationObject?
рандитан

@Randytan, що міститься в моєму приватному сховищі коду, ви можете замінити його на Object. Те саме стосується статичних викликів Logger, замініть їх власним реєстратором (екземпляром).
Маріус

@Marius у objectкласі немає методу getMethods(). Будь-яка порада?
рандитан

127

Ви повинні передати об'єкт, щоб отримати метод поля , так

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

6
чи знаєте ви причину, через яку об'єкт потрібно використовувати у field.get (object) - саме поле походить від цього об’єкта, чому він знову потрібен !?
серуп

18
@serup Ні, об'єкт Field походить від об'єкта Class, який не має зв'язку з вашим фактичним екземпляром. ( object.getClass()поверне вам цей об’єкт класу)
Дмитро Спіхальський,

1
objectу фрагменті не визначено, тому читачі не можуть зрозуміти, як ним користуватися.
Гілтерас

@Ghilteras в цьому випадку вони ще не повинні використовувати рефлексію і спочатку отримувати основні навички 🤷🏻‍♂️. Роздум - це досить передова тема, щоб не пояснити, що змінна objectозначає наш цільовий об'єкт / екземпляр, з яким ми працюємо. Я думаю, що читачі насправді абсолютно в порядку з тим, що є objectу цій відповіді.
Дмитро Спихальський

@RajanPrasad Не дуже. У запитанні є один об’єкт, який має назву "об'єкт". Інші об’єкти мають інші назви. Відповідь є точною та підібраною для запитань та для імен, які використовуються у питанні, щоб зробити речі максимально зрозумілими. Якщо це не працює для вас - я не маю ідеї, як зробити це більш зрозумілим, і вам слід спробувати інші відповіді або, мабуть, поки що не уникати роздумів.
Дмитро Спихальський

19

Я використовую роздуми в реалізації toString () мого класу уподобань, щоб побачити членів та значення класу (проста та швидка налагодження).

Я використовую спрощений код:

@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не визначено, читачі не можуть зрозуміти, як застосувати приклад у відповіді
Ghilteras

2

Я розміщую своє рішення в Котліні, але воно може працювати і з об'єктами Java. Я створюю розширення функції, щоб будь-який об’єкт міг використовувати цю функцію.

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 та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.