Pergunta

Não há uma classe abstrata:

public abstract class AbstractAny {
  private long period;

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

Eu não quero mudar a fonte da classe abstrata, mas necessidade de adicionar alguma flexibilidade sobre como o período de campo está sendo definido. É possível alterar o valor do período de campo de um método anulado? Como por exemplo:

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

Quando tento executar este super.getClass().getDeclaredField("period") código lança java.lang.NoSuchFieldException: period

Foi útil?

Solução

Você precisa getClass().getSuperclass() para obter a superclasse, não super.getClass().

No entanto, eu realmente não recomendo fazer isso. Você está destruindo basicamente o encapsulamento da classe abstrata. Se a classe abstrata não está fornecendo flexibilidade suficiente para os seus descendentes, deve ser fixado - indo em torno dele é apenas a pedir sarilhos. E se algum outro membro das necessidades classe abstrata para ser alterado sempre que isso se faz? Toda a ponto de ter estado privado é para que a classe é capaz de proteger seus próprios dados. Usando reflexão como este é um hack realmente feio que deve ser um absoluto última resort.

Outras dicas

Eu estou com Jon Skeet. É mais fácil a longo prazo para mudar o código fonte do superclasse que quer fazer neste campo protegido ou delegar mutação para um método substituível. Usando reflexão para alterar o valor funciona ok agora, mas não escala muito bem, tanto quanto a manutenção ao longo do tempo vai.

ConcreteSome não está estendendo a classe abstrata AbstractAny.
Tente este

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

deve retornar java.lang.Object

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top