В 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 здесь, казалось бы, будет оцениваться полностью каждый раз, тогда как если бы куча была сделана максимальной кучей при создании экземпляра, вся правая часть выражения могла бы (и должна) просто игнорироваться.


person ecl3ctic    schedule 21.07.2012    source источник


Ответы (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
person Joey    schedule 21.07.2012
comment
В первом примере, что, если вы объявите сам класс как final? - person CAFxX; 21.07.2012
comment
Никаких изменений относительно условного. - person Joey; 21.07.2012

Исходный компилятор исходного кода в байт-код не может оптимизировать значения, которые известны только во время выполнения. Такое значение на самом деле не является «константой» в обычном использовании этого термина. По-настоящему константные выражения, которые можно упростить во время компиляции, упрощаются, я полагаю, поэтому, если у вас есть:

public static final int FOO = 10;
public static final int BAR = 20;

...

System.out.println(FOO * BAR):

Я считаю, что умножение будет выполняться во время компиляции. Однако это невозможно в описанном вами случае, потому что они не являются константами времени компиляции.

Компилятор JIT может обнаружить общие выражения, но вы должны предоставить нам более конкретный пример (в коде, а не просто описание), чтобы обеспечить какую-либо уверенность.

person Jon Skeet    schedule 21.07.2012