10

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

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

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

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

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

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

  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от JAKJ
  • Error: User Rate Limit Exceeded

    от JAKJ
  • Error: User Rate Limit Exceeded

    от JAKJ
  • Error: User Rate Limit Exceeded

    от JAKJ
  • Error: User Rate Limit Exceeded

    от
  • Для тех, кто просто хочет расширить класс во время выполнения, а не изменять тип времени выполнения существующих объектов, см.Extending class at runtime

    от Theodore Murdock
  • Предположим, существующая строка "public static Foo foo = new Foo ();" quot; что я не могу изменить. У меня есть "общедоступный класс Bar extensions Foo" и я хочу сделать & quot; foo = new Bar (...) & quot; так, как если бы первая строка была "public static Foo foo = new Bar ()".

    от JAKJ
  • Пожалуйста, перефразируйте вопрос.

    от Michael Slade
  • Можете ли вы также привести пример того, что вы на самом деле пытаетесь достичь? Вместо желаемого, но, возможно, невозможного способа сделать это.

    от millimoose
  • 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

  • 1

    Вы смотрели на Java Proxies?

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

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

  • 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);
    

    }

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

  • 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/

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