2017-05-27 9 views
0

自分自身を自動的に作成するサブクラスを作成しようとしています。私はインスタンスのリストを保持するBaseを定義しました。次に、固定メンバーregDerivedを定義しました。 regは、Base.Register()を呼び出して初期化され、インスタンスリストに追加されます。Javaで自動初期化された静的オブジェクトを作成する

main()では、インスタンスリストBaseを印刷しています。しかし、初期化はなく、エラーが発生します - インスタンスリストはnullです。

BooleansのリストをBaseに追加しました。インスタンスを登録するたびに、このリストを変更しています。私はまた、このリストをプログラムに印刷します。私はBase.register()の実行を強制することを期待していたが、役に立たなかった。

私はうまくいきましたが、私は感謝しません - Base.register()の結果をDerivedに保存して印刷できました。それは静的な初期化を強制するでしょう。しかし、私は派生クラスの束のためのソリューションを使用するつもりで、私はそれぞれの派生クラスを直接呼び出す必要はありません。

静的なinitを強制する方法はありますか?

私は反射を使うことができると思いますが、私は現時点でそれを避けようとしています。

私が実際にやろうとしているのは、(ユニットテストのための)派生クラスのセットを構築することです。すべてのクラスはBaseを派生します。それぞれ別々にインスタンスを作成する必要性を避けたい。私は、各派生クラスコード(のみ)で汎用ソリューションを取得しようとしています。このようなソリューションは、&ペーストを簡単にコピーできます。

public class StaticTest { 

    private static class Base{ 
     private static ArrayList<Base> _instances = null; 
     private static ArrayList<Boolean> _regs = null; 
     public static int _count = 0; 
     public static void init(){ 
      _regs = new ArrayList<>(); 
      for (int i=0;i<10;i++) 
       _regs.add(false); 
     } 
     protected static boolean register(Base b) 
     { 
      if (_instances == null) 
       _instances = new ArrayList<>(); 

      _regs.set(_count++, true); 

      return _instances.add(b); 
     } 

     public static void printAll(){ 
      for (Boolean b: _regs) 
       System.out.printf("hello %s%n", b.toString()); 
      for (Base b: _instances) 
       System.out.printf("hello %s%n", b.toString()); 
     } 
    } 

    private static class Derived extends Base{ 
     public static boolean _reg = Base.register(new Derived()); 
    } 

    public static void main(String[] args) { 
     //System.out.print(Derived._reg ? "0" : "1"); 
     Base.init(); 
     System.out.printf("Base._count = %d%n",Base._count); 
     Base.printAll(); 
    } 

} 
+1

静的初期化ブロックでクラスを初期化することができます。https://stackoverflow.com/questions/2420389/static-initialization-blocks – Rjiuk

+0

「Base」コンストラクタで各オブジェクトを登録し、派生インスタンスを作成してクライアントクラスとして登録されている必要がありますか? –

+0

編集後も、間違った質問をしています。これはあなたの問題ではなく、あなたが適用しようとしている解決策の問題です。これは間違っています。あなたは子供クラスのシングルトンを望みますか?なぜ親は子のシングルトンへの参照を必要としますか?それは理にかなっていませんが、子の参照を親コンストラクタに保存しないでください(親と子は同じインスタンスです)。 –

答えて

0

簡単な答えは、クラスが最初に使用されたときにのみ静的初期化が行われることです。 Base.init()を呼び出すと、Derivedはまだ使用されていないので、registerは呼び出されていません。

中間の答えは、System.out行のコメントを外すと、initより前に登録するための派生呼び出しの静的コードがArraylistを初期化するため、NullPointerExceptionが発生するということです。 initを最初の行に移動するとそれが解決され、必要に応じて動作します。

最終的な答えは、Javaクラスの初期化の仕方とその限界を理解しようとしている場合ですが、それは問題ありませんが、作成しようとしているメカニズムは非常に悪い設計です。あなたが解決しようとしている真の問題を提供してください。誰かがあなたを正しい方向に向けることができます。

+0

ありがとう、私はオリジナルを編集しました。 – tamir

関連する問題