Получить значение из переменной класса с помощью отражения, а затем использовать методы значения

#java #reflection

#java #отражение

Вопрос:

Я пытаюсь получить значение из переменной класса с помощью отражения. Например, у меня есть Car класс, и у него есть свойство engine. Кроме того, в Engine классе я переопределил toString() метод и определил еще один hello() метод.

И затем, когда я пытаюсь получить значение с помощью

getDeclaredField() метод, похоже, я получаю правильное значение Engine экземпляра, но по некоторым причинам я не могу вызвать метод hello() для него.

Класс Car

 public class Car {
    final Engine engine = new Engine();
}
  

Класс Engine

 public class Engine {

    public void hello() {
        System.out.println("hello");
    }

    @Override
    public String toString() {
        return "Engine";
    }
}

  

Основной класс

 public class Main {
    public static void main(String[] args) {
        try {
            Field field = Car.class.getDeclaredField("engine");
            Object value = field.get(new Car());

            // It's print Engine as expected
            System.out.println(value);

            // But I can't call hello() method
            // value.hello()

        } catch (NoSuchFieldException | IllegalAccessException e) {
            System.out.println("Exception");
        }
    }
}

  

Ответ №1:

Чтобы вызвать hello() метод, сначала убедитесь, что ваш value является экземпляром Engine (используя instanceof ), а затем приведите value к Engine . Нравится,

 // Check type, cast instance and call hello() method
if (value instanceof Engine) {
    ((Engine) value).hello();
}
  

которые вы также можете написать как

 if (value instanceof Engine) {
    Engine.class.cast(value).hello();
}
  

также обычно сохранять Class ссылку и использовать ее вместо жесткого кодирования конкретного объекта, с которым Class вы работаете; например,

 Class<? extends Engine> cls = Engine.class
// ...
if (cls.isAssignableFrom(value.getClass())) {
    cls.cast(value).hello();
}
  

Комментарии:

1. Спасибо, Эллиотт! это работает как шарм! я думал, что когда мы получаем значение из свойства, оно уже имеет правильный тип и т.д.

Ответ №2:

Вам также необходимо вызвать

 field.setAccessible(true);
  

прежде чем пытаться получить к нему доступ.

Хотя это может быть только для закрытых полей, см. @Elliott.Фриш отвечает

Комментарии:

1. Хм, это нужно только для private свойств, не так ли?