tipos - paso de parametros en java
¿Orden de ejecución de los métodos que describen una instancia y un argumento en Java? (4)
El JLS , Java SE 7 Edition tiene el siguiente ejemplo, que dice que es fooFunc()
antes de bazFunc()
, sin embargo, solo puedo encontrar el ejemplo; aún no he encontrado la declaración asociada que lo especifica:
Ejemplo 15.12.4.1-2. Orden de evaluación durante la invocación del método
Como parte de una invocación del método de instancia (§15.12), hay una expresión que denota el objeto a invocar. Esta expresión parece estar completamente evaluada antes de que se evalúe cualquier parte de cualquier expresión de argumento a la invocación del método. Así, por ejemplo, en:
class Test2 { public static void main(String[] args) { String s = "one"; if (s.startsWith(s = "two")) System.out.println("oops"); } }
la aparición de
s
antes de".startsWith"
se evalúa primero, antes de la expresión del argumentos = "two"
. Por lo tanto, una referencia a la cadena"one"
se recuerda como la referencia de destino antes de que la variable local s se cambie para referirse a la cadena"two"
. Como resultado, el métodostartsWith
se invoca para el objeto de destino"one"
con el argumento"two"
, por lo que el resultado de la invocación es falso, ya que la cadena"one"
no comienza con"two"
. De ello se deduce que el programa de prueba no se imprime"oops"
.
En la declaración:
fooFunc().barFunc(bazFunc());
barFunc()
obviamente no puede ejecutar hasta que bazFunc()
y fooFunc()
hayan completado.
¿Pero está garantizado el orden de ejecución de fooFunc()
y bazFunc()
?
Pregunta relacionada (¡pero diferente!): ¿ Orden de ejecución de parámetros garantizados en Java?
La documentación para esto es 15.12.4. Evaluación en tiempo de ejecución de la invocación del método
Dice "En tiempo de ejecución, la invocación del método requiere cinco pasos. Primero, se puede calcular una referencia de destino. En segundo lugar, se evalúan las expresiones de los argumentos. En tercer lugar, se comprueba la accesibilidad del método a invocar. En cuarto lugar, el código real para se localiza el método a ejecutar. En quinto lugar, se crea un nuevo marco de activación, se realiza la sincronización si es necesario y el control se transfiere al código del método ".
En el ejemplo, se llama a fooFunc()
como parte de calcular la referencia de destino, y bazFunc()
es una de las expresiones de argumento, por lo que fooFunc()
debe llamar a fooFunc()
.
Primero fooFunc
, luego bazFunc
y último barFunc
Aquí hay un código que lo demuestra:
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;
}
}
La salida de este código es:
I am fooFunc!
I am bazFunc!
I am barFunc!
fooFunc()
se ejecutará primero, seguido de bazFunc()
y finalmente barFunc()
Todos podemos estar de acuerdo en que fooFunc()
debe ejecutarse antes de que barFunc()
tenga algo sobre lo que operar.
Dado que bazFunc()
solo se llamará cuando barFunc()
necesita sus parámetros, es lógico que esto suceda después de fooFunc()
.