В Java: упрощаются ли выражения, включающие константы, определенные при создании экземпляров, во время компиляции?
Как кратко изложено в моем заголовке, мне было интересно, упрощаются ли выражения, включающие константы, определенные при создании экземпляров, во время компиляции?
Например, у меня есть класс кучи, где у меня есть последний логический isMinHeap, значение которого установлено в конструкторе кучи. Методы кучи затем используют этот логический в определенных местах. Может ли компилятор оптимизировать это, чтобы упростить все эти выражения, включающие этот логический тип, или выражения вычисляются полностью при каждом вызове метода?
Спасибо!
РЕДАКТИРОВАТЬ: потому что кто-то попросил у меня более конкретный пример, вот метод, который вызывается каждый раз, когда узел удаляется из кучи (чтобы помочь с повторной кучи дерева):
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 здесь, по-видимому, будет вычисляться полностью каждый раз, тогда как, если куча была сделана max-heap при создании экземпляра, вся правая часть выражения могла (и должна) просто игнорироваться.
2 ответа
Это очень вероятно, не будет. Во-первых, он все еще не является постоянным для класса во время компиляции; могут быть еще два случая, когда это отличается. И такого рода оптимизация обычно оставляется 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
Исходный компилятор исходного кода не может оптимизировать значения, которые известны только во время выполнения. Такое значение на самом деле не является "константой" в обычном использовании этого термина. Я полагаю, что действительно постоянные выражения, которые можно упростить во время компиляции , упрощаются, так что если у вас есть:
public static final int FOO = 10;
public static final int BAR = 20;
...
System.out.println(FOO * BAR):
Я считаю, что умножение будет выполняться во время компиляции. Однако это невозможно в случае, который вы описываете, потому что они не являются константами времени компиляции.
JIT-компилятор может обнаружить общие выражения, но вам нужно дать нам более конкретный пример (в коде, а не просто в описании), чтобы обеспечить какую-либо определенность.