2009-08-03 17 views
2

抽象クラスがあります:Javaの抽象クラスからプライベートフィールドを変更するにはどうすればよいですか?

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")を実行しようとするあなたはsuper.getClass()、スーパークラスを取得するためにgetClass().getSuperclass()を必要はありませんjava.lang.NoSuchFieldException: period

答えて

20

をスローします。

ただし、I 実際にははおすすめしません。あなたは基本的に抽象クラスのカプセル化を破壊しています。抽象クラスがその子孫に十分な柔軟性を提供していない場合は、修正する必要があります。この抽象クラスの他のメンバが変更される必要がある場合は、それを変更する必要がありますか?私的な状態を持つことの全ポイントは、クラスが自分のデータを保護できるようにすることです。このような反射を使用すると、実際には醜いハックがあります。これは絶対の最後のです。

0

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の

+0

修正しました。ありがとうございます –

2

を返す必要があります。長期的には、スーパークラスのソースコードを変更してこのフィールドを保護するか、またはオーバーライド可能なメソッドに突然変異を委譲する方が簡単です。値を変更するためにリフレクションを使用するとすぐに機能しますが、時間が経つにつれてメンテナンスが行われる限り、それはうまくスケールされません。

関連する問題