sirve settitle rootpane que para definicion java operator-precedence post-increment order-of-evaluation ocpjp

settitle - a=(a++)*(a++) da resultados extraños en Java



para que sirve settitle en java (15)

Estoy estudiando para el examen OCPJP, y por eso tengo que entender cada pequeño detalle extraño de Java. Esto incluye el orden en que los operadores pre y post-incremento se aplican a las variables. El siguiente código me está dando resultados extraños:

int a = 3; a = (a++) * (a++); System.out.println(a); // 12

¿No debería ser la respuesta 11? O tal vez 13? ¡Pero no 12!

SEGUIR:

¿Cuál es el resultado del siguiente código?

int a = 3; a += (a++) * (a++); System.out.println(a);


Aquí está el código java:

int a = 3; a = (a++)*(a++);

Aquí está el bytecode:

0 iconst_3 1 istore_1 [a] 2 iload_1 [a] 3 iinc 1 1 [a] 6 iload_1 [a] 7 iinc 1 1 [a] 10 imul 11 istore_1 [a]

Esto es lo que pasa:

Empuja 3 en la pila, luego saca 3 de la pila y la almacena en a. Ahora a = 3 y la pila está vacía.

0 iconst_3 1 istore_1 a

Ahora empuja el valor de "a" (3) a la pila, y luego incrementa a (3 -> 4).

2 iload_1 [a] 3 iinc 1 1 [a]

Así que ahora "a" es igual a "4" la pila es igual a {3}.

Luego carga "a" nuevamente (4), empuja la pila e incrementa "a".

6 iload_1 [a] 7 iinc 1 1 [a]

Ahora "a" es igual a 5 y la pila es igual a {4,3}

Así que finalmente saca los primeros dos valores de la pila (4 y 3), los multiplica y los almacena nuevamente en la pila (12).

10 imul

Ahora "a" es igual a 5 y la pila es igual a 12.

Finalmente, aparece el 12 de la pila y se almacena en a.

11 istore_1 [a]

Tada!


Cada vez que usas un ++, estás post-incrementando un. Eso significa que la primera a ++ se evalúa como 3 y la segunda se evalúa como 4. 3 * 4 = 12.


En caso de :

int a = 3; a = (a++) * (a++); a = 3 * a++; now a is 4 because of post increment a = 3 * 4; now a is 5 because of second post increment a = 12; value of 5 is overwritten with 3*4 i.e. 12

Por lo tanto obtenemos salida como 12.

En caso de :

a += (a++) * (a++); a = a + (a++) * (a++); a = 3 + (a++) * (a++); // a is 3 a = 3 + 3 * (a++); //a is 4 a = 3 + 3 * 4; //a is 5 a = 15

El punto principal a tener en cuenta aquí es que, en este caso, el compilador está resolviendo de izquierda a derecha y en el caso de un incremento posterior, el valor antes del incremento se usa en el cálculo y, a medida que avanzamos de izquierda a derecha, se usa el valor incrementado.


Existe una falta general de comprensión sobre cómo funcionan los operadores. Sinceramente, cada operador es azúcar sintáctico.

Todo lo que tiene que hacer es entender lo que realmente está sucediendo detrás de cada operador. Supongamos lo siguiente:

a = b -> Operators.set(a, b) //don''t forget this returns b a + b -> Operators.add(a, b) a - b -> Operators.subtract(a, b) a * b -> Operators.multiply(a, b) a / b -> Operators.divide(a, b)

Los operadores compuestos pueden luego reescribirse utilizando estas generalizaciones (por favor, ignore los tipos de devolución por simplicidad):

Operators.addTo(a, b) { //a += b return Operators.set(a, Operators.add(a, b)); } Operators.preIncrement(a) { //++a return Operators.addTo(a, 1); } Operators.postIncrement(a) { //a++ Operators.set(b, a); Operators.addTo(a, 1); return b; }

Puedes reescribir tu ejemplo:

int a = 3; a = (a++) * (a++);

como

Operators.set(a, 3) Operators.set(a, Operators.multiply(Operators.postIncrement(a), Operators.postIncrement(a)));

Que se puede dividir utilizando múltiples variables:

Operators.set(a, 3) Operators.set(b, Operators.postIncrement(a)) Operators.set(c, Operators.postIncrement(a)) Operators.set(a, Operators.multiply(b, c))

Ciertamente es más detallado de esa manera, pero de inmediato se hace evidente que nunca desea realizar más de dos operaciones en una sola línea.


Los incrementos de prefijo y post prefijo tienen una mayor prioridad que el operador de multiplicación. por lo tanto la expresión se evalúa como 3 * 4.


Si usa un ++ la próxima vez que lo use se incrementa en uno. Así que estás haciendo

a = 3 * (3 + 1) = 3 * 4 = 12


Son las 12. La expresión comienza evaluándose desde la izquierda. Así lo hace:

a = (3++) * (4++);

Una vez que se evalúa la primera parte (3 ++), a es 4, por lo que en la siguiente parte hace a = 3 * 4 = 12. Tenga en cuenta que el último incremento posterior (4 ++) se ejecuta pero no tiene efecto ya que a se le asigna el valor 12 después de esto.


Su declaración:

a += (a++) * (a++);

es equivalente a cualquiera de esos:

a = a*a + 2*a a = a*(a+2) a += a*(a+1)

Usa cualquiera de esos en su lugar.


Todos han explicado claramente la primera expresión y por qué el valor de a es 12.

Para la siguiente pregunta, la respuesta es totalmente obvia para el observador casual:

17


(a++) es un incremento posterior, por lo que el valor de expresión es 3.

(a++) es un incremento posterior, por lo que el valor de expresión ahora es 4.

La evaluación de la expresión está ocurriendo de izquierda a derecha.

3 * 4 = 12


(a++) significa devolver ay incrementa, por lo que (a++) * (a++) significa 3 * 4


a++ significa ''el valor de a, y a se incrementa en 1''. Así que cuando corres

(a++) * (a++)

el primer a++ se evalúa primero, y produce el valor 3. a entonces se incrementa en 1. El segundo a++ luego se evalúa. a produce el valor de 4, y luego se incrementa de nuevo (pero esto no importa ahora)

Así que esto se convierte en

a = 3 * 4

que es igual a 12.


Después de la primera, a++ a convierte en 4. Así que tienes 3 * 4 = 12 .

( a convierte en 5 después del segundo a++ , pero eso se descarta, porque la asignación a = anula)


Ejemplo 1

int a = 3; a = (++a) * (a++); System.out.println(a); // 16

Ejemplo 2

int a = 3; a = (++a) * (++a); System.out.println(a); // 20

Solo para asegurarse de dónde colocar la expresión ++ que cambia el valor según la ubicación.


int a = 3; a += (a++) * (a++);

Primero construye el árbol de sintaxis:

+= a * a++ a++

Para evaluarlo comienza con el elemento más exterior y el descenso recursivamente. Para cada elemento haga:

  • Evaluar a los niños de izquierda a derecha
  • Evaluar el elemento mismo

El operador += es especial: se expande a algo como left = left + right , pero solo evalúa la expresión una vez. Aún así, el lado izquierdo se evalúa en un valor (y no solo una variable) antes de que el lado derecho se evalúe en un valor.

Esto lleva a:

  1. Empezar a evaluar +=
  2. Evaluar el lado izquierdo de la asignación a la variable a .
  3. Evalúe la variable a al valor 3 que se usará en la suma.
  4. Empezar a evaluar *
  5. Evalúa el primer a++ . Esto devuelve el valor actual de un 3 y establece a a 4
  6. Evalúa el segundo a++ . Esto devuelve el valor actual de un 4 y establece a a 5
  7. Calcula el producto: 3 * 4 = 12
  8. Ejecutar += . El lado izquierdo había sido evaluado a 3 en el tercer paso y el lado derecho es 12 . Entonces asigna 3 + 12 = 15 a a .
  9. El valor final de a es 15.

Una cosa a tener en cuenta aquí es que la precedencia del operador no tiene influencia directa en el orden de evaluación. Solo afecta a la forma del árbol, y por lo tanto indirectamente al orden. Pero entre los hermanos en el árbol, la evaluación siempre es de izquierda a derecha, independientemente de la precedencia del operador.