Search code examples
javareflectionabstract-classprivate-members

How to mutate a private field from the abstract class in Java?


There's an abstract class:

public abstract class AbstractAny {
  private long period;

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

I don't want to change the source of the abstract class but need to add some flexibility on how the field period is being set. Is it possible to change the value of the field period from an overriden method? Like for example:

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

When I try to run this code super.getClass().getDeclaredField("period") throws java.lang.NoSuchFieldException: period


Solution

  • You need getClass().getSuperclass() to get the superclass, not super.getClass().

    However, I really don't recommend doing this. You're basically destroying the encapsulation of the abstract class. If the abstract class isn't providing enough flexibility for its descendants, it should be fixed - going around it is just asking for trouble. What if some other member of the abstract class needs to be changed whenever this one does? The whole point of having private state is so that the class is able to guard its own data. Using reflection like this is a really ugly hack which should be an absolute last resort.