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?
&&
es unand
operador lógico , lo que significa quea
debe tener los valores 1, 2 y 3 al mismo tiempo, lo que es lógicamente imposible. La respuesta es NO, no es posible. ¿Desea escribir unaif
declaración que verifique sia
tiene uno de los valores 1, 2 O 3?yes
_
, excepto que no puede verlo.if(a==1 && a==2 && a==3)
no necesariamente se evalúa al mismo tiempo. Y eso se puede usar para hacer que esto funcione sin tener que recurrir a trucos Unicode.Respuestas:
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 lo prueba constantemente
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
else {System.out.println("Failure");}
cláusula, verá que la prueba falla con mucha más frecuencia de la que tiene éxito).En la práctica, también funciona sin declararlo
a
como volátil, pero solo 21 veces en mi MacBook. Sinvolatile
, el compilador o HotSpot puede almacenar en cachéa
o reemplazar laif
declaración conif (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 dea
. Convolatile
, sigue imprimiendo "Éxito" para siempre.fuente
volatile
, pero en principio, esto puede suceder incluso sin lavolatile
palabra clave y podría suceder un número arbitrario de veces, mientras que, por otro lado, no hay garantía de que suceda, incluso convolatile
. Pero, por supuesto, tener que ocurra en la práctica, es tranquilo impresionante ...volatile
. Las barreras de memoria creadas para implementarvolatile
disminuyen la velocidad de los subprocesos y hacen que sea más probable que funcionen sincronizados durante cortos períodos de tiempo. Sucede mucho más a menudo de lo que esperaba. Es muy sensible al tiempo, pero veo aproximadamente que entre 0.2% y 0.8% de las evaluaciones de(a == 1 && a == 2 && a == 3)
retornotrue
.Usando conceptos (y código) de una respuesta de golf de código brillante , los
Integer
valores pueden ser alterados.En este caso, puede hacer que
int
s se convierta enInteger
s igual cuando normalmente no serían:Desafortunadamente, no es tan elegante como la respuesta multiproceso de Erwin Bolwidt (ya que esta requiere un
Integer
casting) , pero aún tienen lugar algunas travesuras divertidas.fuente
Integer
. Es una pena lo del reparto, pero sigue siendo genial.a
estar configurado en 1/2/3 satisfaráa == 1
, pero no va para otro ladoJava
. La versión menos fea que pude encontrar fue usara.equals(1) && a.equals(2) && a.equals(3)
, lo que obliga1
,2
y3
ser autoboxed comoInteger
s.a
una claseboolean equals(int i){return true;}
?Integer a = 1;
en la línea anterior, todavía está claro quea
realmente es un número entero.En esta pregunta, @aioobe sugiere (y desaconseja) el uso del preprocesador C para las clases Java.
Aunque es extremadamente tramposo, esa es mi solución:
Si se ejecuta utilizando los siguientes comandos, generará exactamente uno
Success
:fuente
a
es una variable, pero puede ser cualquier fragmento de código arbitrario en idiomas con un preprocesador.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 debe 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 se imprime
Success!
en 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 aquí .
Esto funciona porque los nombres de las variables se toman de diferentes alfabetos. Son identificadores distintos, que crean dos variables distintas con un valor diferente en cada uno.
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):
(Espero que nunca tenga que lidiar con ese tipo de problema en el futuro).
fuente
а
ya
funcione, siempre que le diga a su editor en qué codificación está (y posiblemente también el compilador). Todas las codificaciones Unicode funcionan (UTF-8, UTF-16 (en BE o LE), UTF-32, incluso UTF-7), así como, por ejemplo, Windows-1251, ISO 8859-5, KOI8-R.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
Integer.valueOf(...)
llamada. El siguiente enfoque se basa en modificar el desempaquetado automático al cambiar laInteger.intValue()
llamada.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.
fuente
access$nnn
métodos utilizados para leerprivate
campos de clases internas / externas? Eso permitiría algunas otras variantes interesantes (que incluso funcionan con unaint
variable) ...(Integer)2
) encajona el int. Mirando más en la reflexión , parece que no es posible hacer esto con unboxing usando la reflexión, pero puede ser posible con Instrumentation en su lugar (o con PowerMock, como en esta respuesta)access$0
y la existencia de un método se verifica en el registro. Pero el reemplazo nunca se invoca.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:
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
utiliza dos identificadores que son iguales, al menos desde el punto de vista Unicode. Simplemente usan diferentes formas de codificar el mismo carácter
ä
, usandoU+00E4
yU+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.
fuente
int ᅠ2 = 3;
es intencional? Porque, estoy viendo un código muy extraño por todas partesa
), mientras que se trata de espacios en blanco, y bueno, está dando crédito a las respuestas aún más antiguas en la pregunta de JavaScript relacionada. Tenga en cuenta que mi comentario allí es incluso más antiguo que la pregunta de Java (por varios días) ...Inspirado por la excelente respuesta de @ 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
just-in-time
compilador optimiza dicho código).El truco consiste en deshabilitar cualquier
JIT
optimización utilizando la siguienteVM
opción:En esta situación, el número de casos de éxito aumenta significativamente. Aquí está el código:
Las transmisiones paralelas de PS se usan
ForkJoinPool
debajo del capó, y la variable a se comparte entre múltiples subprocesos sin ninguna sincronización, es por eso que el resultado no es determinista.fuente
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:
fuente