Вопрос по inheritance, java – Java: расширение класса во время выполнения

10

У меня есть возможность расширить класс во время компиляции, но мне нужно иметь возможность создавать экземпляр этого подкласса во время выполнения, используя экземпляр суперкласса, который уже был создан.

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

У меня нет доступа к программе в достаточной степени, чтобы изменить экземпляр на мой подкласс или прервать исходный экземпляр.

Вариант использования: существует существующий массив экземпляров класса X. Мой код загружается после. Мне нужно переопределить один из методов одного из экземпляров X с помощью моего загруженного подкласса Y, расширяющего X. Родительская программа обращается к объектам только через этот массив, поэтому я хочу заменить этот элемент массива моим экземпляром Y, но для этого нужно ведут себя так, как если бы он был изначально создан в этом массиве. Я не могу просто заключить экземпляр суперкласса и переадресовать вызовы, и возникают сложности с повторной реализацией суперкласса.

Я надеюсь, что это более понятно.

Для тех, кто просто хочет расширить класс во время выполнения, а не изменять тип времени выполнения существующих объектов, см.Extending class at runtime Theodore Murdock
Пожалуйста, перефразируйте вопрос. Michael Slade
Можете ли вы также привести пример того, что вы на самом деле пытаетесь достичь? Вместо желаемого, но, возможно, невозможного способа сделать это. millimoose
Предположим, существующая строка "public static Foo foo = new Foo ();" quot; что я не могу изменить. У меня есть "общедоступный класс Bar extensions Foo" и я хочу сделать & quot; foo = new Bar (...) & quot; так, как если бы первая строка была "public static Foo foo = new Bar ()". JAKJ

Ваш Ответ

4   ответа
3

CGLIB:

cglib is a powerful, high performance and quality Code Generation Library, It is used to extend JAVA classes and implements interfaces at runtime

Вы можете найти несколько примеров здесь: https://github.com/cglib/cglib/wiki

5

В JVM существует экземпляр ClassA. Вы хотели бы динамически изменить иерархию классов ClassA так, чтобы существовал новый класс под названием ClassB, который происходит от ClassA. Затем вы хотели бы создать экземпляр экземпляра ClassB, но иметь реализацию его подкласса, аналогичную существующему экземпляру ClassA. Что-то вроде замены памяти.

Вы можете посмотреть вhttp://www.jboss.org/javassist , Что вам нужно сделать, это заменить ClassLoader, затем определить, когда ClassA загружается, а затем создается его экземпляр. Затем вам нужно создать ClassB и вернуть его вместо этого.

Update

После небольшого исследования все еще есть возможность сделать то, что вы хотите. IDE, такие как Eclipse, поддерживают реализации метода HotSwap во время отладки. Они используют Instrumentation API.

http://zeroturnaround.com/blog/reloading_java_classes_401_hotswap_jrebel/

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

Error: User Rate Limit Exceeded JAKJ
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded JAKJ
Error: User Rate Limit Exceeded JAKJ
1

Вот фрагмент из Javadoc:

«Динамический прокси-класс (просто называемый прокси-классом ниже) - это класс, который реализует список интерфейсов, указанных во время выполнения, когда класс создается».

Error: User Rate Limit Exceeded JAKJ
2

public static Foo foo = new Foo();

и вы хотите заменить его на Bar, который расширяет Foo сделайте Bar оберткой для Foo и используйте рефлексию, чтобы foo указала на ваш экземпляр Bar.

public class Foo extends Bar {
  private bar; 
  public Foo(Bar oldInstance) {
     this.bar = oldInstance;
  }
}

а также

// exception handling ommitted
public static void onStartup() {
   Class fooRefClass = FooRef.class;
   Field fooRef = fooRefClass.getDeclaredField("foo");

   Foo foo = (Foo)fooRef.get(null);
   Bar bar = new Bar(foo);
   fooRef.set(null, bar);

}

Как я уже сказал, я не знаю, возможно ли это в вашем случае.

Похожие вопросы