由于在这种情况下您可以控制源代码,因此最好重构类以满足您的需求而不是使用反射(这不仅成本高昂,而且根据您的安全策略被禁止)。
常用的技术是Holder pattern。有关更多信息,请参阅 Joshua Bloch 的 Effective Java(第 2 版)第 71 条。我们还可以通过使用线程安全的非阻塞结构来避免读取同步,即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
}
}
事实上,因为解析操作可能非常非常快(与同步相比),我们可以完全取消同步。所以我们最终可能会多次解析这个值——这并不是一个大问题,因为每次的结果都是一样的。见布洛赫等人。更多信息请参阅第 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
}
}