2017-09-08 17 views
1

Java静的初期化に問題があります。私がしたいのは、汎用定数を持つ型チェックと、型と型名を変換することです。だから、私はインターフェイスMCにいくつかの型付き定数を持ち、名前に型を変換するために内部クラス型のハッシュマップを持っています。 Java外部クラス静的初期化

MC.Type.getValue("MInteger")
を呼び出すと、内部クラスの型が初期化されますが、外部クラスMCの静的定数ではなく、戻り値は nullです。 Javaでこれらの定数を初期化するにはどうすればよいですか?私はできるでしょう

static { Type<?> dummy = MC.MBoolean; }

クラスタイプですが、これを行うには良い方法はありません。あるいは、私はこれを完全に間違ってやっています。

import java.util.HashMap; 
import java.util.Map; 

interface MC { 
    public static final Type<Boolean> MBoolean = new Type<>("MBoolean"); 
    public static final Type<Integer> MInteger = new Type<>("MInteger"); 

    public static class Type<T> { 
     private static final Map<String, Type<?>> types = new HashMap<>(); 
     private final String name; 

     private Type(String name) { 
      this.name = name; 
      types.put(name, this); 
     } 

     public String getName() { 
      return name; 
     } 

     public static Type<?> getValue(String name) { 
      return types.get(name); 
     } 
    } 
} 

public class Main { 

    public static void main(String[] args) { 
     System.out.println(MC.Type.getValue("MInteger")); 
     MC.MBoolean.getName(); 
     System.out.println(MC.Type.getValue("MInteger")); 
    } 
} 

答えて

1

すべてTypeのインスタンスがあなたのMCクラスに含まれているので、この問題を解決するための非常に直接的なアプローチは、その静的初期化子にTypeのコンストラクタからType.typesマップとクラスの登録を移動するには、次のようになります。

private static final Map<String, Type<?>> types = new HashMap<>(); 
static { 
    types.put(MBoolean.getName(), MBoolean); 
    types.put(MInteger.getName(), MInteger); 
} 
private Type(String name) { 
    this.name = name; 
    // removed types.put(name, this); from here 
} 

Demo.

1

あなたはどちらか静的初期化子ブロック使用することができます。

private static final Map<String, Type<?>> types = new HashMap<>(); 

static { 
    types.put(MC.MBoolean.getName(), MC.MBoolean); 
    types.put(MC.MInteger.getName(), MC.MInteger); 
} 

又はダブルブレース初期

private static final Map<String, Type<?>> types = new HashMap<>() {{ 
    put(MC.MBoolean.getName(), MC.MBoolean); 
    put(MC.MInteger.getName(), MC.MInteger); 
}}; 

まず、中括弧はHashMapの新しい匿名サブクラスを作成し、第二の中括弧は、構築時に実行されるインスタンス初期化ブロック(引数なしコンストラクタであります匿名クラスの場合)。

+0

は恐ろしいです...不条理マインド@ –

+0

は、なぜあなたはそう思いますか?私の意見では、ハッシュマップの作成と静的イニシャライザを介したinitilazationの分割よりも簡潔です。 – matoni

+0

デバッグとシリアライズで混乱するクラスを作成するためです。さらに、タイトなループで使用すると計算時間が増え、多くの場合(特に1.7とそれ以前の悪)、余分なメモリが使用されます。また、これは初心者のプログラマによってメンテナンス性が低下するという誤解を招く可能性があります。これは構文上の砂糖とはまったく混同されません。幸いなことに、Java 9ではこれを廃止する方法が追加されました。要するに、欠点は利益に値するものではない。 –

0

MC.MBooleanを明示的に呼び出さない限り、コンストラクタは初期化されません。 double braceの初期化を行う方がよいでしょう。ハッシュマップを初期化するために、匿名クラスを作成

private static final Map<String, Type<?>> types = new HashMap<>() { 
      { 
       put(MC.MBoolean.getName(), MC.MBoolean); 
       put(MC.MInteger.getName(), MC.MInteger); 
      } 
     }; 
関連する問題