Отражение Java: как переопределить или сгенерировать методы во время выполнения? - PullRequest
25 голосов
/ 28 июня 2009

В простой 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), (поэтому мы запрещаем доступ к локальным полям).

Ответы [ 5 ]

10 голосов
/ 28 июня 2009

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

9 голосов
/ 28 июня 2009

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

8 голосов
/ 28 июня 2009

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

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

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

8 голосов
/ 28 июня 2009

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

Для классов вам потребуется либо сторонняя библиотека, либо написать немало кода. Как правило, динамическое создание классов таким способом - создание пробников для тестирования.

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

0 голосов
/ 28 июня 2009

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

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

...