una - tipos de variables en java ejemplos
¿Cómo puede una variable Java ser diferente de sí misma? (10)
Me pregunto si esta pregunta se puede resolver en Java (soy nuevo en el lenguaje). Este es el código:
class Condition {
// you can change in the main
public static void main(String[] args) {
int x = 0;
if (x == x) {
System.out.println("Ok");
} else {
System.out.println("Not ok");
}
}
}
Recibí la siguiente pregunta en mi laboratorio: ¿Cómo se puede omitir el primer caso (es decir, hacer que la condición x == x
falsa) sin modificar la condición en sí?
Cree su propio System
clase en el mismo paquete con la Condition
.
En este caso, su clase System
ocultará la clase java.lang.System
class Condition
{
static class System
{
static class out
{
static void println(String ignored)
{
java.lang.System.out.println("Not ok");
}
}
}
public static void main (String[] args) throws java.lang.Exception
{
int x = 0;
if (x == x)
{
System.out.println("Not ok");
}
else
{
System.out.println("Ok");
}
}
}
Hay tantas soluciones:
class A extends PrintStream {
public A(PrintStream x) {super(x);}
public void println(String x) {super.println("Not ok");}
public static void main(String[] args) {
System.setOut(new A(System.out));
int x = 0;
if (x == x) {
System.out.println("Ok");
} else {
System.out.println("Not ok");
}
}
}
La línea reemplazada podría leer.
double x = Double.NaN;
Esto causaría que se imprima el gotcha.
La especificación de lenguaje Java (JLS) dice:
Los operadores de punto flotante no producen excepciones (§11). Una operación que se desborda produce un infinito con signo, una operación que subdesborda produce un valor desnormalizado o un cero firmado, y una operación que no tiene un resultado matemáticamente definido produce NaN. Todas las operaciones numéricas con NaN como operando producen NaN como resultado. Como ya se ha descrito, NaN no está ordenado, por lo que una operación de comparación numérica que involucre uno o dos NaNs devuelve falso y cualquier comparación! = Que involucre a NaN devuelve verdadero, incluyendo x! = X cuando x es NaN.
No estoy seguro de si esta es una opción, pero cambiar x
de la variable local a un campo permitiría que otro subproceso cambie su valor entre el lado izquierdo y el derecho de lectura en el enunciado if
.
Aquí hay una breve demostración:
class Test {
static int x = 0;
public static void main(String[] args) throws Exception {
Thread t = new Thread(new Change());
t.setDaemon(true);
t.start();
while (true) {
if (x == x) {
System.out.println("Ok");
} else {
System.out.println("Not ok");
break;
}
}
}
}
class Change implements Runnable {
public void run() {
while (true)
Test.x++;
}
}
Salida:
⋮
Ok
Ok
Ok
Ok
Ok
Ok
Ok
Ok
Not ok
Por las especificaciones del lenguaje Java NaN
no es igual a NaN
.
Por lo tanto, cualquier línea que causara que x
sea igual a NaN
podría causar esto, como
double x=Math.sqrt(-1);
De las especificaciones de lenguaje Java:
Los operadores de punto flotante no producen excepciones (§11). Una operación que se desborda produce un infinito con signo, una operación que subdesborda produce un valor desnormalizado o un cero firmado, y una operación que no tiene un resultado matemáticamente definido produce NaN. Todas las operaciones numéricas con NaN como operando producen NaN como resultado. Como ya se ha descrito, NaN no está ordenado, por lo que una operación de comparación numérica que involucre uno o dos NaNs devuelve falso y cualquier comparación! = Que involucre a NaN devuelve verdadero, incluyendo x! = X cuando x es NaN.
Una forma simple es usar Float.NaN
:
float x = Float.NaN; // <--
if (x == x) {
System.out.println("Ok");
} else {
System.out.println("Not ok");
}
Not ok
Puedes hacer lo mismo con Double.NaN
.
De JLS §15.21.1. Operadores de Igualdad Numérica ==
y !=
:
La prueba de igualdad de punto flotante se realiza de acuerdo con las reglas del estándar IEEE 754:
Si cualquiera de los operandos es NaN, entonces el resultado de
==
esfalse
pero el resultado de!=
Estrue
.De hecho, la prueba
x!=x
estrue
si y solo si el valor dex
es NaN....
Una solución fácil es:
System.out.println("Gotcha!");if(false)
if( a == a ){
System.out.println("Not yet...");
} else {
System.out.println("Gotcha!");
}
Pero no conozco todas las reglas de este enigma ...
:) Sé que esto es una trampa, pero sin conocer todas las reglas, ¿es esta la solución más sencilla a la pregunta? :)
Usando el mismo enfoque de salto / cambio de salida de otra respuesta:
class Condition {
public static void main(String[] args) {
try {
int x = 1 / 0;
if (x == x) {
System.out.println("Ok");
} else {
System.out.println("Not ok");
}
} catch (Exception e) {
System.out.println("Not ok");
}
}
}
Gotcha!
obtener un Gotcha!
de esto:
volatile Object a = new Object();
class Flipper implements Runnable {
Object b = new Object();
public void run() {
while (true) {
Object olda = a;
a = b;
a = olda;
}
}
}
public void test() {
new Thread(new Flipper()).start();
boolean gotcha = false;
while (!gotcha) {
// I''ve added everything above this - I would therefore say still legal.
if (a == a) {
System.out.println("Not yet...");
} else {
System.out.println("Gotcha!");
// Uncomment this line when testing or you''ll never terminate.
//gotcha = true;
}
}
}
int x = 0;
if (x == x) {
System.out.println("Not ok");
} else {
System.out.println("Ok");
}