3 回答
TA贡献1772条经验 获得超8个赞
microoptimization(但在标准库的情况下可能很重要),以及:
#inertia:这种模式在 90 年代的 C 程序员中很常见,所以计算机科学的巨头可能仍然使用这种风格。
除非性能真的很关键,否则为新的业务逻辑编写这样的代码是没有意义的。
(微)优化:
javac(JDK 11) 为原始(“坏”)版本生成的字节码比(更好的)代码少一个 JVM 操作。为什么?JDK 的版本“使用”赋值运算符的返回值(而不是从变量加载值)进行if条件评估。
然而,这更多是对javac优化可能性的限制,而不是编写可读性较差的代码的原因。
这是问题中引用的 JDK 版本的字节码:
0: aload_2
1: invokestatic #2 // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
4: pop
5: aload_0
6: aload_1
7: invokevirtual #3 // Method get:(Ljava/lang/Object;)Ljava/lang/Object;
10: dup
11: astore_3
12: ifnonnull 39
15: aload_2
16: aload_1
17: invokeinterface #4, 2 // InterfaceMethod java/util/function/Function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
22: dup
23: astore 4
25: ifnull 39
28: aload_0
29: aload_1
30: aload 4
32: invokevirtual #5 // Method put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
35: pop
36: aload 4
38: areturn
39: aload_3
40: areturn
以下是更易读版本的字节码:
public V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
final V v = get(key);
if (v == null) {
final V newValue = mappingFunction.apply(key);
if (newValue != null) {
put(key, newValue);
return newValue;
}
}
return v;
}
.. 字节码是:
0: aload_2
1: invokestatic #2 // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
4: pop
5: aload_0
6: aload_1
7: invokevirtual #3 // Method get:(Ljava/lang/Object;)Ljava/lang/Object;
10: astore_3
11: aload_3
12: ifnonnull 40
15: aload_2
16: aload_1
17: invokeinterface #4, 2 // InterfaceMethod java/util/function/Function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
22: astore 4
24: aload 4
26: ifnull 40
29: aload_0
30: aload_1
31: aload 4
33: invokevirtual #5 // Method put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
36: pop
37: aload 4
39: areturn
40: aload_3
41: areturn
TA贡献1797条经验 获得超4个赞
我认为这主要是偏好问题;我的印象是 Doug Lea 更喜欢这种简洁的风格。但是如果您查看该方法的原始版本,它会更有意义一些,因为它与newValuewhich 确实需要内联分配配对:
default V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
V v, newValue;
return ((v = get(key)) == null &&
(newValue = mappingFunction.apply(key)) != null &&
(v = putIfAbsent(key, newValue)) == null) ? newValue : v;
}
TA贡献1858条经验 获得超8个赞
我同意:这是一种代码味道,我绝对更喜欢第二个版本。
如果您有循环,那么在单个表达式中对赋值和比较的神秘使用可能会导致代码更短,例如:
V v;
while ((v = getNext()) != null) {
// ... do something with v ...
}
要消除代码异味,您需要更多代码,并且需要在两个地方分配变量:
V v = getNext();
while (v != null) {
// ...
v = getNext();
}
或者你需要在赋值后移动循环退出条件:
while (true) {
V v = getNext();
if (v == null)
break;
// ...
}
对于if语句,它当然没有任何意义。即使是循环,我也会避免它。
添加回答
举报