Зарегистрируйтесь, чтобы продолжить обучение

Рефлексия Java: ООП

Рефлексия — это механизм, который позволяет программе получать информацию о своей собственной структуре и поведении во время выполнения, включая классы, методы, поля и другие элементы. Это позволяет программе динамически создавать и манипулировать объектами, вызывать методы и получать доступ к полям, не зная заранее их имен или типов. Рефлексия широко используется в таких областях, как тестирование, отладка и создание фреймворков и библиотек

Использование рефлексии

Рефлексия в Java может быть использована для различных целей, таких как динамическое создание и манипулирование объектами, вызов методов и доступ к полям классов без знания их имен или типов заранее, получение доступа к приватным полям

Класс, с которым будем работать

public class Test {
    private String value;

    private Test(String value) {
        this.value = value;
    }

    public Test() {}

    public String getValue() {
        return value;
    }

    private void setValue (String value) {
        this.value = value;
    }

    public String toString() {
        return "Test{value='" + value + "'}";
    }
}

Получение списка полей и методов

public class Main {

    public static void getClassInfo (Object obj) {
        Class<?> aClass = obj.getClass(); // Class Test
        Method[] methods = aClass.getDeclaredMethods(); // [public java.lang.String Test.getValue()]
        Field[] fields = aClass.getFields();// []
        Field[] declaredFields = aClass.getDeclaredFields(); // [private java.lang.String Test.value]
        Constructor<?>[] constructors = aClass.getConstructors(); // [public Test()]

        System.out.println(aClass);
        System.out.println(Arrays.tostring(methods));
        System.out.println(Arrays.toString (fields));
        System.out.println(Arrays.toString(declaredFields));
        System.out.println(Arrays.toString(constructors));
    }

    public static void main (String[] args) {
        var test = new Test();
        getClassInfo(test);
    }
}

Получение доступа к приватным полям

class Main {
    public static void setPrivateValue(Object obj, String fieldName, String newValue) {
        Class<?> aClass = obj.getclass();

        try {
            Field field = aClass.getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(obj, newValue);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public static void main (String[] args) {
        var test = new Test();
        System.out.println(test);
        setPrivateValue(test, "value", "newValue");
        System.out.printin(test);

    }
}

Вызов конструкторов

class Main {
    public static Test createTestobjectWithValue(String value) {
        try {
            var constructor = Test.class.getDeclaredConstructor(String.class); // Получение конструктора класса
            constructor.setAccessible(true); // Изменение прав доступа к метода
            return constructor.newInstance(value); // Создание нового объекта
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    public static void main (String[] args) {
        var test = createTestObjectwithValue("newvalue");
        System.out.println(test); //=> Test {value= 'newValue'}
    }
}

Вызов метода по имени

class App {
    public static void callPrivateMethod(Object obj, String methodName, String parameter) {
        Class<?> aClass = obj.getClass();

        try {
            Method method = aClass.getDeclaredMethod(methodName, String.class)
            method.setAccessible(true);
            method.invoke(obj, parameter);
        } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public static void main (String[] args) {
        var test = new Test();
        System.out.println(test); //=> Test{value=null)
        callPrivateMethod(test, "setValue", "newValue");
        System.out.println(test); //=> Test{value=newValue)
    }
}

Аннотации

Определение собственной аннотации

@Retention(RetentionPolicy.RUNTIME) // Видимость аннотации: SOURCE, CLASS, RUNTIME
@Target (ElementType.METHOD) // Типы аннотируемых элементов: TYPE, FIELD, METHOD, PARAMETER и пр.
public @interface Cmd {
    String name(); // Параметры аннотаций
    String description();
}

Использование созданной аннотации

public class Commands {

    private final Map<String, String> availableCommands;

    public Commands() {
        this.availableCommands = new HashMap<>();
        var methods = this.getClass().getDeclaredMethods();

        for (Method method : methods) {
            if (method.isAnnotationPresent(Cmd.class)) {
                Cmd cmdInfo = method.getAnnotation(Cmd.class);
                availableCommands.put(cmdInfo.name(), cmdInfo.description());
            }
        }
    }

    @Cmd(name = "Exit", description = "ExitApplication")
    public void exit() {
        System.out.println("exit");
    }

    @Cmd (name = "Help", description = "Show all available commands")
    public void printHelp() {
        StringBuilder builder = new StringBuilder();
        availableCommands.forEach((key, value) -> builder.append(key).append(": ").append(value).append("\n"));
        System.out.println(builder);
    }
}
class Main {

    public static void main (String[] args) {
        var commands = new Commands();
        commands.printHelp();
    }
}

Дополнительные материалы

  1. Reflection API

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 25 000 ₸ в месяц
Разработка приложений на языке Java
10 месяцев
с нуля
Старт 13 марта

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»