Сначала оценивается индекс массива или присвоенное значение?

Если у меня есть следующий код:

array[index] = someValue;

сначала выполняется оценка someValue или index?

Ответ 1

Сначала оценивается индекс. См. JLS раздел 15.26.1, в частности:

15.26.1. Простой оператор присваивания =

...

Если левый операнд является выражением доступа к массиву (§15.13), возможно, заключен в одну или несколько пар круглых скобок, а затем:

  • Во-первых, подвыражение ссылки массива левого операнда оценивается выражение доступа к массиву. Если эта оценка завершается резко, тогда выражение присваивания резко завершается для та же самая причина; подвыражение индекса (из левого массива операндов выражение доступа), а правый операнд не оценивается, и нет выполняется присваивание.

  • В противном случае подвыражение индекса левого массива операндов оценивается выражение доступа. Если эта оценка завершится внезапно, то выражение присваивания внезапно завершается по той же причине и правый операнд не оценивается и не выполняется присвоение.

  • В противном случае оценивается правый операнд. Если эта оценка завершается внезапно, тогда выражение присваивания резко завершается по той же причине, и никакого назначения не происходит.

TL; DR: порядок равен 1 [2] = 3

Ответ 2

Похоже, сначала выполняется выражение index.

Эта тестовая программа подтверждает это:

public class Main {
   public static void main(String[] args) {
      int[] array = new int[10];
      array[getIndex()] = getValue();
   }


   private static int getIndex() {
      System.out.println("getIndex!");
      return 0;
   }

   private static int getValue() {
      System.out.println("getValue!");
      return 1;
   }
}

Вывод:

getIndex!
getValue!

Значение оценивается, даже если выбрано ArrayIndexOutOfBoundsException. Изменение getIndex():

private static int getIndex() {
   System.out.println("getIndex!");
   return -1;  // Hey!
}

Вывод:

getIndex!
getValue!
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
    at Main.main(Main.java:11)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)