Pregunta

Hay una clase abstracta:

public abstract class AbstractAny {
  private long period;

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

No quiero cambiar la fuente de la clase abstracta, pero necesito agregar algo de flexibilidad sobre cómo se establece el período de campo. ¿Es posible cambiar el valor del período de campo de un método anulado? Como por ejemplo:

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

Cuando intento ejecutar este código super.getClass (). getDeclaredField (" period ") arroja java.lang.NoSuchFieldException: period

¿Fue útil?

Solución

Necesita getClass (). getSuperclass () para obtener la superclase, no super.getClass () .

Sin embargo, realmente no recomiendo hacer esto. Básicamente estás destruyendo la encapsulación de la clase abstracta. Si la clase abstracta no proporciona suficiente flexibilidad para sus descendientes, debe repararse; dar vueltas solo es pedir problemas. ¿Qué pasa si algún otro miembro de la clase abstracta necesita ser cambiado cada vez que este lo hace? El objetivo de tener un estado privado es que la clase pueda proteger sus propios datos. Usar un reflejo como este es un truco realmente feo que debería ser un último último recurso.

Otros consejos

Estoy con Jon Skeet. A la larga, es más fácil cambiar el código fuente de la superclase para proteger este campo o delegar la mutación a un método reemplazable. Usar la reflexión para cambiar el valor funciona bien ahora, pero no escala muy bien en lo que respecta al mantenimiento a lo largo del tiempo.

ConcreteSome no extiende la clase abstracta AbstractAny.
Prueba esto

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

debería devolver java.lang.Object

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top