Подтвердить что ты не робот

Отражение Java: как переопределить или сгенерировать методы во время выполнения?

В простой Java можно переопределить метод класса программно во время выполнения (или даже создать новый метод)?

Я хочу иметь возможность сделать это, даже если я не знать классы во время компиляции.

То, что я имею в виду, переопределив во время выполнения:

abstract class MyClass{
  public void myMethod();
}

class Overrider extends MyClass{
  @Override
  public void myMethod(){}
}

class Injector{
  public static void myMethod(){ // STATIC !!!
    // do actual stuff
  }
}

// some magic code goes here
Overrider altered = doMagic(
    MyClass.class, Overrider.class, Injector.class);

Теперь этот вызов...

altered.myMethod();

... будет вызывать Injector.myMethod() вместо Overrider.myMethod().

Injector.myMethod() - статический, потому что после выполнения "магии" он вызывается из другого экземпляра класса (это Overrider), (поэтому мы не позволяем ему получать доступ к локальным полям).

4b9b3361

Ответ 1

Вы можете использовать что-то вроде cglib для генерации кода на лету

Ответ 2

В java6 добавлена ​​возможность преобразования любого уже загруженного класса. Взгляните на changes в пакете java.lang.instrument

Ответ 3

Для интерфейсов есть java.lang.reflect.Proxy.

Для классов вам понадобится библиотека сторонних разработчиков или напишите справедливый бит кода. Обычно динамическое создание классов таким образом - это создание mocks для тестирования.

Существует также API-интерфейс инструментария, который позволяет модифицировать классы. Вы также можете изменять классы с помощью специального загрузчика классов или только файлы классов на диске.

Ответ 4

Я написал статью для java.net о том, как прозрачно добавлять инструкции журнала в класс, когда он загружается загрузчиком классов, используя java agent.

Он использует библиотеку Javassist для управления байтовым кодом, в том числе с использованием компилятора Javassist для генерации дополнительного байт-кода, который затем вставлен в соответствующее место, а затем результирующий класс предоставляется загрузчику классов.

Уточненная версия доступна с проектом slf4j.

Ответ 5

Если я правильно понял, основная проблема, которая вас беспокоит, заключается в том, как передать делегат статического метода (например, на С#) через метод интерфейса экземпляра.

Вы можете проверить эту статью: Программист Java Посмотрит на делегатов С#, в котором показано, как получить ссылку на ваш статический метод и вызовите его. Затем вы можете создать класс-оболочку, который принимает имя статического метода в своем конструкторе и реализует ваш базовый класс для вызова статического метода из метода экземпляра.