正如我在标题中总结的那样,我想知道涉及在实例化时定义的常量的表达式是否会在编译时得到简化?
例如,我有一个堆类,其中有一个最终 boolean 值 isMinHeap,其值在堆的构造函数中设置。堆的方法然后在某些地方使用这个 boolean 值。编译器可以优化它以简化所有这些涉及此 boolean 值的表达式,还是每次调用方法时都计算完整的表达式?
谢谢!
编辑: 因为有人问我一个更具体的例子,这里有一个方法,每次从堆中移除一个节点时都会调用(以协助重新堆化树):
private boolean requiresRepositioningDown(BTNode<T> node)
{
boolean childIsSmaller = (node.getLeft().getValue().compareTo(
node.getValue()) < 0)
|| (node.getRight() != null && node.getRight().getValue().compareTo(
node.getValue()) < 0);
if (isMinHeap && childIsSmaller || !isMinHeap && !childIsSmaller)
return true;
else
return false;
}
这里带有 isMinHeap 的表达式似乎每次都会得到完整的计算,而如果堆在实例化时被设为最大堆,则可以(并且应该)忽略表达式的整个右侧。
最佳答案
很可能不会。首先,它在编译时仍然不是常量类;仍然有两个不同的例子。这种优化通常留给 JIT 编译器。
即使您的常量从未设置为任何其他值,也不会对其进行优化。例如
public class Heap {
final boolean isMinHeap;
public Heap() {
isMinHeap = true;
}
@Override
public String toString() {
if (isMinHeap) return "Min!";
return "Not Min";
}
}
编译为
public java.lang.String toString();
Code:
0: aload_0
1: getfield #2 // Field isMinHeap:Z
4: ifeq 10
7: ldc #3 // String Min!
9: areturn
10: ldc #4 // String Not Min
12: areturn
请注意,条件仍然存在。如果经常使用该方法,JIT 编译器可能会选择完全删除它,因为它应该知道 final
成员不能更改。但这有点难以观察。
如果您立即将 isMinHeap
设置为一个值,而不是在构造函数中执行此操作,然后将执行优化:
public class Heap {
final boolean isMinHeap = true;
public Heap() {
}
@Override
public String toString() {
if (isMinHeap) return "Min!";
return "Not Min";
}
}
将 toString
编译为:
public java.lang.String toString();
Code:
0: ldc #3 // String Min!
2: areturn
关于java - 在 Java 中 : do expressions involving constants defined at instantiation get simplified during compile-time?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11590517/