web-dev-qa-db-fra.com

Comment une variable Java Java peut-elle être différente d'elle-même?

Je me demande si cette question peut être résolue en Java (je suis nouveau dans le langage). Voici le code:

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");
        }
    }
}

J'ai reçu la question suivante dans mon laboratoire: comment pouvez-vous ignorer le premier cas (c'est-à-dire faire le x == x condition false) sans modifier la condition elle-même?

106
Husam

Une façon simple consiste à utiliser Float.NaN :

float x = Float.NaN;  // <--

if (x == x) {
    System.out.println("Ok");
} else {
    System.out.println("Not ok");
}
Pas d'accord

Vous pouvez faire de même avec Double.NaN .


De JLS §15.21.1. Opérateurs d'égalité numérique == et != :

Les tests d'égalité en virgule flottante sont effectués conformément aux règles de la norme IEEE 754:

  • Si l'un des opérandes est NaN, le résultat de == est false mais le résultat de != est true.

    En effet, le test x!=x est true si et seulement si la valeur de x est NaN.

...

170
arshajii
int x = 0;
if (x == x) {
    System.out.println("Not ok");
} else {
    System.out.println("Ok");
}
157
Jeroen Vannevel

Par le Spécifications du langage JavaNaN n'est pas égal à NaN.

Par conséquent, toute ligne qui a fait que x soit égal à NaN entraînerait cela, comme

double x=Math.sqrt(-1);

À partir du Java Spécifications du langage:

Les opérateurs en virgule flottante ne produisent aucune exception (§11). Une opération qui déborde produit un infini signé, une opération qui déborde produit une valeur dénormalisée ou un zéro signé, et une opération qui n'a pas de résultat mathématiquement défini produit NaN. Toutes les opérations numériques avec NaN comme opérande produisent en conséquence NaN. Comme cela a déjà été décrit, NaN n'est pas ordonné, donc une opération de comparaison numérique impliquant un ou deux NaN renvoie faux et toute comparaison! = Impliquant NaN renvoie vrai, y compris x! = x lorsque x est NaN.

147
Richard Tingle

Je ne sais pas si c'est une option, mais changer x de variable locale en champ permettrait à un autre thread de changer sa valeur entre la lecture à gauche et à droite dans l'instruction if.

Voici une courte démo:

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++;
    }
}

Production:

⋮
Ok
Ok
Ok
Ok
Ok
Ok
Ok
Ok
Not ok
72
Pshemo

La ligne remplacée pouvait lire.

double x = Double.NaN;

Cela entraînerait l'impression du gotcha.

La spécification du langage Java (JLS) dit:

Les opérateurs en virgule flottante ne produisent aucune exception (§11). Une opération qui déborde produit un infini signé, une opération qui déborde produit une valeur dénormalisée ou un zéro signé, et une opération qui n'a pas de résultat mathématiquement défini produit NaN. Toutes les opérations numériques avec NaN comme opérande produisent en conséquence NaN. Comme cela a déjà été décrit, NaN n'est pas ordonné, donc une opération de comparaison numérique impliquant un ou deux NaN renvoie faux et toute comparaison! = Impliquant NaN renvoie vrai, y compris x! = X lorsque x est NaN.

55
Mex

J'ai réussi à obtenir un Gotcha! à partir de ceci:

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;
    }
  }
}
30
OldCurmudgeon

Il y a tellement de solutions:

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");
        }
    }
}
25
Johannes Kuhn

Une solution simple est:

System.out.println("Gotcha!");if(false)
if( a == a ){
  System.out.println("Not yet...");
} else {
  System.out.println("Gotcha!");
}

Mais je ne connais pas toutes les règles de cette énigme ...

:) Je sais que c'est une triche, mais sans connaître toutes les règles, est-ce la solution la plus simple à la question :)

25
Christian Kuetbach

Créez votre propre classe System dans le même paquet avec Condition.
Dans ce cas, votre classe System masquera Java.lang.System classe

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");
        }
    }
}  

Ideone DEMO

11
Ilya

En utilisant la même approche de sortie de saut/changement d'une autre réponse:

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");
        }
    }
}
9
higuaro