operadores metodo logicos ejemplos declarar comparar java

metodo - ¿Puede(a== 1 && a== 2 && a== 3) evaluar como verdadero en Java?



metodo boolean java (8)

Sabemos que puede en JavaScript .

¿Pero es posible imprimir el mensaje "Éxito" en la condición dada a continuación en Java?

if (a==1 && a==2 && a==3) { System.out.println("Success"); }

Alguien sugirió:

int _a = 1; int a = 2; int a_ = 3; if (_a == 1 && a == 2 && a_ == 3) { System.out.println("Success"); }

Pero al hacer esto, estamos cambiando la variable real. ¿Hay alguna otra manera?


Como ya sabemos que es posible hacer que este código se evalúe como verdadero gracias a las excelentes respuestas de Erwin Bolwidt y phflack , quería mostrarle que necesita mantener un alto nivel de atención cuando se trata de una condición similar a la presentada en la pregunta, ya que a veces lo que ves puede no ser exactamente lo que crees que es.

Este es mi intento de mostrar que este código imprime Success! a la consola Sé que hice trampa un poco , pero sigo pensando que este es un buen lugar para presentarlo aquí mismo.

No importa cuáles sean los propósitos de escribir código como este: es mejor saber cómo lidiar con la siguiente situación y cómo verificar si no está equivocado con lo que cree que ve.

Usé el cirílico ''a'' que es un carácter distinto del latín ''a''. Puede inspeccionar los caracteres utilizados en la declaración if here .

Esto funciona porque los nombres de las variables se toman de diferentes alfabetos. Son identificadores distintos, creando dos variables distintas con un valor diferente en cada una.

Tenga en cuenta que si desea que este código funcione correctamente, la codificación de caracteres debe cambiarse a una que admita ambos caracteres, por ejemplo, todas las codificaciones Unicode (UTF-8, UTF-16 (en BE o LE), UTF-32, incluso UTF-7 ), o Windows-1251, ISO 8859-5, KOI8-R (gracias - Thomas Weller y Paŭlo Ebermann - por señalarlo):

public class A { public static void main(String[] args) { int а = 0; int a = 1; if(а == 0 && a == 1) { System.out.println("Success!"); } } }

(Espero que nunca tenga que lidiar con ese tipo de problema en el futuro).


Dado que esto parece ser un seguimiento de esta pregunta de JavaScript , vale la pena señalar que este truco y otros similares también funcionan en Java:

public class Q48383521 { public static void main(String[] args) { int aᅠ = 1; int ᅠ2 = 3; int a = 3; if(aᅠ==1 && a==ᅠ2 && a==3) { System.out.println("success"); } } }

En Ideone

Pero tenga en cuenta que esto no es lo peor que podría hacer con Unicode. El uso de espacios en blanco o caracteres de control que son partes de identificadores válidos o el uso de letras diferentes que se ven iguales todavía crea identificadores que son diferentes y se pueden detectar, por ejemplo, cuando se realiza una búsqueda de texto.

Pero este programa

public class Q48383521 { public static void main(String[] args) { int ä = 1; int ä = 2; if(ä == 1 && ä == 2) { System.out.println("success"); } } }

usa dos identificadores que son iguales, al menos desde el punto de vista Unicode. Simplemente usan diferentes formas de codificar el mismo carácter ä , usando U+00E4 y U+0061 U+0308 .

En Ideone

Por lo tanto, dependiendo de la herramienta que esté utilizando, es posible que no solo se vean iguales, sino que las herramientas de texto habilitadas para Unicode ni siquiera informan ninguna diferencia, siempre encuentran ambas al buscar. Incluso puede tener el problema de que las diferentes representaciones se pierden al copiar el código fuente a otra persona, tal vez tratando de obtener ayuda para el "comportamiento extraño", haciéndolo no reproducible para el ayudante.


En líneas similares , forzando un flotador (o doble) a un flujo inferior (o desbordamiento) a través de la división (o multiplicación) por un gran número:

int a = 1; if (a / Float.POSITIVE_INFINITY == 1 / Float.POSITIVE_INFINITY && a / Float.POSITIVE_INFINITY == 2 / Float.POSITIVE_INFINITY && a / Float.POSITIVE_INFINITY == 3 / Float.POSITIVE_INFINITY) { System.out.println("Success"); }


En esta pregunta, @aioobe sugiere (y desaconseja) el uso del preprocesador C para las clases Java.

Aunque es extremadamente engañoso, esa es mi solución:

#define a evil++ public class Main { public static void main(String[] args) { int evil = 1; if (a==1 && a==2 && a==3) System.out.println("Success"); } }

Si se ejecuta utilizando los siguientes comandos, generará exactamente un Success :

cpp -P src/Main.java Main.java && javac Main.java && java Main


Hay otra forma de abordar esto (además del enfoque volátil de carreras de datos que publiqué anteriormente), utilizando el poder de PowerMock. PowerMock permite que los métodos sean reemplazados por otras implementaciones. Cuando eso se combina con el desempaquetado automático, la expresión original (a == 1 && a == 2 && a == 3) , sin modificación, puede hacerse realidad.

La respuesta de @ phflack se basa en modificar el proceso de auto-boxeo en Java que usa la llamada Integer.valueOf(...) . El siguiente enfoque se basa en modificar el desempaquetado automático al cambiar la llamada Integer.intValue() .

La ventaja del siguiente enfoque es que la declaración if original dada por el OP en la pregunta se usa sin cambios, lo que creo que es el más elegante.

import static org.powermock.api.support.membermodification.MemberMatcher.method; import static org.powermock.api.support.membermodification.MemberModifier.replace; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @PrepareForTest(Integer.class) @RunWith(PowerMockRunner.class) public class Ais123 { @Before public void before() { // "value" is just a place to store an incrementing integer AtomicInteger value = new AtomicInteger(1); replace(method(Integer.class, "intValue")) .with((proxy, method, args) -> value.getAndIncrement()); } @Test public void test() { Integer a = 1; if (a == 1 && a == 2 && a == 3) { System.out.println("Success"); } else { Assert.fail("(a == 1 && a == 2 && a == 3) != true, a = " + a.intValue()); } } }


Inspirado por la excelente answer @ Erwin, escribí un ejemplo similar, pero usando Java Stream API .

Y una cosa interesante es que mi solución funciona, pero en casos muy raros (porque el compilador just-in-time optimiza dicho código).

El truco consiste en deshabilitar cualquier optimización JIT utilizando la siguiente opción de VM :

-Djava.compiler=NONE

En esta situación, el número de casos de éxito aumenta significativamente. Aquí está el código:

class Race { private static int a; public static void main(String[] args) { IntStream.range(0, 100_000).parallel().forEach(i -> { a = 1; a = 2; a = 3; testValue(); }); } private static void testValue() { if (a == 1 && a == 2 && a == 3) { System.out.println("Success"); } } }

Las transmisiones paralelas de PS usan ForkJoinPool debajo del capó, y la variable a se comparte entre múltiples subprocesos sin sincronización, por eso el resultado no es determinista.


Sí, es bastante fácil lograr esto con múltiples hilos, si declaras que la variable a es volátil.

Un hilo cambia constantemente la variable a de 1 a 3, y otro hilo prueba constantemente que a == 1 && a == 2 && a == 3 . Ocurre con la frecuencia suficiente para tener un flujo continuo de "Éxito" impreso en la consola.

(Tenga en cuenta que si agrega una cláusula else {System.out.println("Failure");} , verá que la prueba falla con mucha más frecuencia de la que tiene éxito).

En la práctica, también funciona sin declarar a como volátil, pero solo 21 veces en mi MacBook. Sin volatile , el compilador o HotSpot puede almacenar en caché o reemplazar la instrucción if (false) con if (false) . Lo más probable es que HotSpot se active después de un tiempo y lo compile en instrucciones de ensamblaje que guarden en caché el valor de a . Con volatile , sigue imprimiendo "Éxito" para siempre.

public class VolatileRace { private volatile int a; public void start() { new Thread(this::test).start(); new Thread(this::change).start(); } public void test() { while (true) { if (a == 1 && a == 2 && a == 3) { System.out.println("Success"); } } } public void change() { while (true) { for (int i = 1; i < 4; i++) { a = i; } } } public static void main(String[] args) { new VolatileRace().start(); } }


Usando conceptos (y código) de una respuesta de golf de código brillante , se pueden Integer valores Integer .

En este caso, puede hacer que int s se convierta en Integer s igual cuando normalmente no serían:

import java.lang.reflect.Field; public class Test { public static void main(String[] args) throws Exception { Class cache = Integer.class.getDeclaredClasses()[0]; Field c = cache.getDeclaredField("cache"); c.setAccessible(true); Integer[] array = (Integer[]) c.get(cache); // array[129] is 1 array[130] = array[129]; // Set 2 to be 1 array[131] = array[129]; // Set 3 to be 1 Integer a = 1; if(a == (Integer)1 && a == (Integer)2 && a == (Integer)3) System.out.println("Success"); } }

Desafortunadamente, no es tan elegante como la respuesta multiproceso de Erwin Bolwidt (ya que esta requiere un casting de Integer ) , pero aún tienen lugar algunas travesuras divertidas.