Могу ли я удалить метод из экземпляра класса в Java?

#java #methods #reflection

#java #методы #отражение

Вопрос:

Допустим, у меня есть класс с именем Foo с некоторыми методами:

  public class Foo{
    public void a(){
       //stuff
    }

    public void b(){
       //stuff
    }
 }
  

И у меня есть экземпляр Foo:
Foo instanceOfFoo = new Foo();

Могу ли я удалить метод ‘a’ из ‘instanceOfFoo’?

Комментарии:

1. не могли бы вы перефразировать свой вопрос? ничего не произойдет, если вы удалите объявление функции, предполагая, что оно содержит 0 ссылок

2. Что вы подразумеваете под удалением? Что должно произойти, если кто-то вызовет этот метод в этом экземпляре?

3. Я голосую за то, чтобы закрыть этот вопрос как не относящийся к теме, потому что этот вопрос явно не имеет смысла.

4. Это похоже на вопрос XY. Чего вы пытаетесь достичь с помощью этого подхода? Как указывалось в ответах, это невозможно без изменения байт-кода во время выполнения. Возможно, вы можете достичь своей цели с помощью менее сложного подхода?

Ответ №1:

Вы не можете удалить метод, не изменив байтовый код и не нарушив «контракт» кода, но вы можете расширить класс и переопределить метод дочернего класса, вызывающий исключение UnsupportedOperationException при вызове. Также дочерний класс должен отказаться от метода и объяснить в своем javadoc обоснование этого и что использовать вместо него.

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

Например:

 public class Foo {
    public void a() {
        // stuff
    }

    public void b() {
        // stuff
    }
}
  

 public class FooChild extends Foo {
    /**
     * @deprecated: This method should no longer be used and will throw an exception
     */
    @Override
    @Deprecated
    public void a() {
        String text = "The method a is no longer supported";
        throw new UnsupportedOperationException(text);
    }
}
  

Ответ №2:

Короткий ответ: Нет, не совсем.

Длинный ответ: Если вы можете контролировать ClassLoader используемый для загрузки Foo класс, вы можете перехватить запрос на загрузку класса Foo и использовать ASM или Javassist для изменения байт-кода класса перед его загрузкой.