阅读源代码时,我偶然发现了JDK源代码中的这种方法。请注意v
和newValue
的声明和初始化。我们这里有'好'的未定义值,赋值在比较中,这是'很好的',还有为了更糟的可读性而添加的额外括号。以及其他的代码坏味道。
default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
V v;
if ((v = get(key)) == null) {
V newValue;
if ((newValue = mappingFunction.apply(key)) != null) {
put(key, newValue);
return newValue;
}
}
return v;
}
但是为什么呢?相对于简单的方式(最好使用否定的 v
比较),按照上述方式编写代码是否有实际好处呢?
default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
V v = get(key);
if (v == null) {
V newValue = mappingFunction.apply(key);
if (newValue != null) {
put(key, newValue);
return newValue;
}
}
return v;
}
除了炫耀Java构造,还有我不知道的实际好处吗?与“简单”方式相比,是不是更好一些?
v
不是本地变量,它可以防止在设置和读取v
之间更改v
时出现竞争条件。但这里唯一的好处似乎只是吓退人们不去动这段代码 :-) - Michael ButscherConcurrentMap
,对吧?你可能想要链接到确切的源代码和版本以使其更清晰。我在许多JDK类中都看到过这种情况;这可能是作者的习惯用法,但并不真正遵守严格的样式指南。无论如何,这是一个相关的问题。 - Mick Mnemonic