我是编程和Java的新手.我注意到,在Java API中,if语句中有一些奇怪的赋值方法.
以下是Map界面的示例:
default V replace(K key, V value) {
V curValue;
if (((curValue = get(key)) != null) || containsKey(key)) {
curValue = put(key, value);
}
return curValue;
}
Run Code Online (Sandbox Code Playgroud)
以这种方式嵌套赋值是否有某种好处?这纯粹是一种风格选择吗?为什么不在curValue
第一次声明时进行赋值?
// why not do it like this?
default V replace(K key, V value) {
V curValue = get(key); // not nested
if (curValue != null || containsKey(key)) {
curValue = put(key, value);
}
return curValue;
}
Run Code Online (Sandbox Code Playgroud)
我在Map界面和其他地方的许多新添加的Java 8方法中都注意到了这一点.这种嵌套分配的形式似乎是不必要的.
编辑:Map界面中的另一个示例:
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;
}
Run Code Online (Sandbox Code Playgroud)
它所做的实际上是复制到局部变量,这会产生更小的字节代码,并且它被视为绝对极端的优化方式,您将在 jdk 代码中的许多其他地方看到这一点。
另一件事是,多次读取局部变量意味着仅读取共享变量一次,例如,如果该变量是 avolatile
并且您只需读取它一次并在方法中使用它。
编辑
据我所知,这两种方法之间的区别在于一次读取
假设我们有这两个方法:
V replace(K key, V value) {
V curValue;
if ((curValue = map.get(key)) != null || map.containsKey(key)) {
curValue = map.put(key, value);
}
return curValue;
}
V replaceSecond(K key, V value) {
V curValue = map.get(key); // write
if (curValue != null || map.containsKey(key)) { // read
curValue = map.put(key, value); // write
}
return curValue;
}
Run Code Online (Sandbox Code Playgroud)
其字节码几乎相同,除了:replaceSecond
将具有:
astore_3 // V curValue = map.get(key); store to curValue
aload_3 // curValue != null; read the value from curValue
Run Code Online (Sandbox Code Playgroud)
虽然该replace
方法将是:
dup // duplicate whatever value came from map.get(key)
astore_3 // store the value, thus "consuming" it form the stack
Run Code Online (Sandbox Code Playgroud)
根据我的理解,dup
这不算是另一次阅读,所以我想这就是所谓的极限优化?
归档时间: |
|
查看次数: |
263 次 |
最近记录: |