Порядок выполнения методов, описывающих экземпляр и аргумент в Java?
В заявлении:
fooFunc().barFunc(bazFunc());
barFunc()
, очевидно, не может выполняться до тех пор, пока не будут завершены как bazFunc()
, так и fooFunc()
.
Но гарантирован ли порядок выполнения fooFunc()
и bazFunc()
?
Связанный (но другой!) вопрос: Порядок выполнения гарантийных параметров в Java?
Ответы
Ответ 1
Документация для этого 15.12.4. Оценка времени выполнения метода.
В нем говорится: "Во время выполнения вызов метода требует пять шагов: во-первых, можно вычислить целевую ссылку. Во-вторых, вычисляются выражения аргументов. В-третьих, проверяется доступность метода для вызова. В-четвертых, фактический код для выполняемого метода. В-пятых, создается новый кадр активации, при необходимости выполняется синхронизация, и управление передается коду метода.
В этом примере fooFunc()
вызывается как часть вычисления целевой ссылки, а bazFunc()
- одно из выражений аргументов, поэтому сначала нужно вызвать fooFunc()
.
Ответ 2
JLS, Java SE 7 Edition имеет следующий пример, который говорит fooFunc()
перед bazFunc()
, однако я могу только найти пример - я еще не нашел связанный оператор, который указывает его:
Пример 15.12.4.1-2. Порядок оценки во время вызова метода
В качестве части вызова метода экземпляра (§15.12), существует выражение, которое обозначает объект, подлежащий вызову. Это выражение представляется полностью оценивается перед любой частью любого выражения аргумента методу вычисляется вызов. Так, например, в:
class Test2 {
public static void main(String[] args) {
String s = "one";
if (s.startsWith(s = "two"))
System.out.println("oops");
}
}
сначала выполняется оценка s
до ".startsWith"
, прежде чем выражение аргумента s = "two"
. Поэтому ссылка на string "one"
запоминается как целевая ссылка перед локальным переменная s изменяется для ссылки на строку "two"
. В результате Метод startsWith
вызывается для целевого объекта "one"
с аргументом "two"
, поэтому результат вызова является ложным, так как строка "one"
не начинается с "two"
. Из этого следует, что тестовая программа не напечатать "oops"
.
Ответ 3
Сначала fooFunc
, затем bazFunc
и last barFunc
Вот какой код, который его демонстрирует:
public class OrderJava {
public static void main(String[] args) {
fooFunc().barFunc(bazFunc());
}
public static Bar fooFunc() {
System.out.println("I am fooFunc!");
return new Bar();
}
public static class Bar {
public void barFunc(Object o) {
System.out.println("I am barFunc!");
}
}
public static Object bazFunc() {
System.out.println("I am bazFunc!");
return null;
}
}
Вывод этого кода:
I am fooFunc!
I am bazFunc!
I am barFunc!
Ответ 4
fooFunc()
выполнит сначала, затем bazFunc()
и, наконец, barFunc()
Мы все можем согласиться с тем, что fooFunc()
должен выполняться до того, как barFunc()
будет работать.
Учитывая, что bazFunc()
вызывается только тогда, когда barFunc()
нуждается в его параметрах, разумно, что это произойдет после fooFunc()
.