Как изменить частное поле из абстрактного класса в Java?

StackOverflow https://stackoverflow.com/questions/1222480

Вопрос

Есть абстрактный класс:

public abstract class AbstractAny {
  private long period;

  public void doSomething() {
    // blah blah blah
    period = someHardcodedValue;
    // blah blah blah
  }
}

Я не хочу менять источник абстрактного класса, но мне нужно добавить некоторую гибкость в настройке периода поля. Можно ли изменить значение периода поля из переопределенного метода? Как например:

public class ConcreteSome extends AbstractAny{
  @Override
  public void doSomething() {
    try {
      Field p = super.getClass().getDeclaredField("period");
      p.setAccessible(true);
      p.setLong(this, 10L);
    } catch (SecurityException e) {
        throw new RuntimeException(e);
    } catch (NoSuchFieldException e) {
        throw new RuntimeException(e);
    } catch (IllegalArgumentException e) {
        throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    }
  }
}

Когда я пытаюсь запустить этот код, super.getClass (). getDeclaredField (" period ") выбрасывает java.lang.NoSuchFieldException: period

Это было полезно?

Решение

Вам нужен getClass (). getSuperclass () , чтобы получить суперкласс, а не super.getClass () .

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

Другие советы

Я с Джоном Скитом. В конечном счете, проще изменить исходный код суперкласса, чтобы либо сделать это поле защищенным, либо делегировать мутацию переопределяемому методу. Использование отражения для изменения значения теперь работает нормально, но оно не очень хорошо масштабируется с точки зрения обслуживания с течением времени.

ConcreteSome не расширяет абстрактный класс AbstractAny.
Попробуйте это

public class ConcreteSome {
    @Override
    public void doSomething() {
        Class<?> clazz = getClass().getSuperclass();
        System.out.println(clazz);
        Field p = clazz.getDeclaredField("period");
        ...

должен вернуть java.lang.Object

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top