この場合、ソースコードを制御できるため、リフレクションを使用するよりも、ニーズに合わせてクラスをリファクタリングすることをお勧めします(これは高価であるだけでなく、セキュリティポリシーによっては禁止されています)。
一般的に使用される手法はHolder pattern
です。詳細については、Joshua BlochのEffectiveJava(2nd Edition)Item71を参照してください。スレッドセーフで非ブロッキング構造、つまりを使用することで、読み取りの同期を回避することもできますjava.util.concurrent.ConcurrentHashMap
。
public class ColorFactory {
private static class ColorFactoryHolder {
// creates on instantiation of ColorFactoryHolder
// synchronization is baked into the JVM, but won't be created until
// the class is used, see JLS 12.4.1
static final ColorFactory instance = new ColorMap();
}
public static ColorFactory getInstance() { return ColorFactoryHolder.instance; }
// concurrent hash map - all operations are thread safe
Map<String,Color> colormap = new ConcurrentHashMap<String,Color>();
private final Object lock = new Object();
private ColorFactory() {
colormap.add("blue",new Color(0,0,255));
// rest of colors here
}
public Color getColor(String spec) {
if(colormap.containsKey(spec)) return colormap.get(spec);
// don't synchronize externally - Bloch et al, item 70
synchronized(lock) {
// double check idiom - not broken, as map is thread safe
if(colormap.containsKey(spec)) return colormap.get(spec);
Color color = parse(spec); // parse method can be extracted from old code
colormap.put(spec,color);
return color;
}
}
private static Color parse(String spec) {
// parse the color spec here
}
}
実際、解析操作は(同期と比較して)非常に高速である可能性が高いため、同期を完全になくすことができます。したがって、値を複数回解析することになります。結果は毎回同じになるため、それほど大きな問題ではありません。Blochetal。を参照してください。詳細については、項目69を参照してください。
public class ColorFactory {
private static class ColorFactoryHolder {
// same as above, snipped for brevity
}
public static ColorFactory getInstance() { return ColorFactoryHolder.instance; }
// requires ConcurrentMap reference to get putIfAbsent(K,V) method
ConcurrentMap<String,Color> colormap = new ConcurrentHashMap<String,Color>();
// private final Object lock = new Object(); - removed
private ColorFactory() {
colormap.add("blue",new Color(0,0,255));
// rest of colors here
}
public Color getColor(String spec) {
Color result = colormap.get(spec);
if(result == null) {
result = parse(spec); // may parse multiple times, but still
// cheaper than synchronization
colormap.putIfAbsent(spec,result);
}
return result
}
private static Color parse(String spec) {
// parse the color spec here
}
}