@SuppressWarnings("unchecked")
private T createExtension(String name) {
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
throw findException(name);
}
try {
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
// ************************************************************ //
EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
// ************************************************************ //
}
injectExtension(instance);
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (wrapperClasses != null && wrapperClasses.size() > 0) {
for (Class<?> wrapperClass : wrapperClasses) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
type + ") could not be instantiated: " + t.getMessage(), t);
}
}
问题描述不清不楚
EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
这句话为什么总分开写呢,我发现里面有很多这种写法,为什么不通过这种呢
instance = EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
看起来舒服吧,而且彼此间不影响,用起来也舒服
@debugmoney
在java8之前这么分开写是最优的,为了降低程序计算量,避免(T) clazz.newInstance()每次都执行,这也是java不支持函数式惰性求值的弊端.
在java8 之后 可以通过computeIfAbsent方法来解决,你可以去了解下java8的computeIfAbsent方法,了解后,这个问题就很清楚了。
java8之后可以这么写:
EXTENSION_INSTANCES.computeIfAbsent(clazz, clazz -> (T) clazz.newInstance());
@debugmoney 你给的写法,结果是 错的。
PS: 有想法要自己先验证一下正确与否哦~ 😓 如果脑子推理不清,就写个测试/Demo的代码来验证。
更多信息可以看ConcurrentHashMap#putIfAbsent的JavaDoc
验证代码如下:
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class Test {
public static void main(String[] args) {
final ConcurrentMap<String, String> map11 = new ConcurrentHashMap<String, String>();
System.out.println(map11.putIfAbsent("key1", "v1")); // output null ! Wrong !!
System.out.println(map11.putIfAbsent("key1", "v2")); // output v1
System.out.println(map11.putIfAbsent("key1", "v3")); // output v1
// Output is: (Wrong value, Bug!)
// null
// v1
// v1
final ConcurrentMap<String, String> map22 = new ConcurrentHashMap<String, String>();
map22.putIfAbsent("key1", "v1");
System.out.println(map22.get("key1")); // output v1 , Right.
map22.putIfAbsent("key1", "v2");
System.out.println(map22.get("key1")); // output v1
map22.putIfAbsent("key1", "v3");
System.out.println(map22.get("key1")); // output v1
// Output is:
// v1
// v1
// v1
}
}
另外, @wuwen5
在java8之前这么分开写是最优的,为了降低程序计算量,避免(T) clazz.newInstance()每次都执行,这也是java不支持函数式惰性求值的弊端.
java8之前因为无computeIfAbsent方法,分开写与不分开写一样,(T) clazz.newInstance()都是每次执行。
对的,不好意思,我之前对提的问题理解有偏差,我关注到点的是那段先get,然后判断空的这段逻辑,我之前的回答是解释的这一段代码的原因。
@oldratlee 确实对putIfAbsent认识不清,第一次key不存在时会返回null
@debugmoney 大胆假设,小心求证;缺一不可。 😄
Nice