[java] Java 변수가 그 자체와 어떻게 다를 수 있습니까?

이 질문을 Java로 해결할 수 있는지 궁금합니다 (저는 언어를 처음 사용합니다). 다음은 코드입니다.

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

실습에서 다음과 같은 질문을 받았습니다. x == x조건 자체를 수정하지 않고 첫 번째 사례를 건너 뛰려면 (즉, 조건을 false로 설정) 어떻게해야합니까?



답변

한 가지 간단한 방법은 다음을 사용하는 것입니다 Float.NaN.

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

if (x == x) {
    System.out.println("Ok");
} else {
    System.out.println("Not ok");
}
안좋아

으로도 똑같이 할 수 있습니다 Double.NaN.


에서 JLS §15.21.1. 수치 평등 연산자 ==!= :

부동 소수점 동등성 테스트는 IEEE 754 표준의 규칙에 따라 수행됩니다.

  • 피연산자가 NaN이면의 결과 ==false이지만 결과는 !=입니다 true.

    실제로 테스트 x!=xtrue의 값 x이 NaN 인 경우에만 수행됩니다 .


답변

int x = 0;
if (x == x) {
    System.out.println("Not ok");
} else {
    System.out.println("Ok");
}


답변

에 의해 Java 언어 사양 NaN 과 동일하지 않습니다 NaN.

따라서 다음과 같이 x같게 된 모든 줄은 NaN다음과 같이 발생합니다.

double x=Math.sqrt(-1);

Java 언어 사양에서 :

부동 소수점 연산자는 예외를 생성하지 않습니다 (§11). 오버플로하는 연산은 부호있는 무한대를 생성하고 언더 플로하는 연산은 비정규 화 된 값 또는 부호있는 0을 생성하며, 수학적으로 명확한 결과가없는 연산은 NaN을 생성합니다. NaN을 피연산자로 사용하는 모든 숫자 연산은 결과로 NaN을 생성합니다. 이미 설명했듯이 NaN은 순서가 지정되지 않았으므로 하나 또는 두 개의 NaN을 포함하는 숫자 비교 연산은 false를 반환 하고 NaN을 포함하는 모든! = 비교는 x가 NaN 일 때 x! = x를 포함하여 true를 반환합니다.


답변

이것이 옵션인지 확실하지 않지만 x지역 변수에서 필드로 변경하면 다른 스레드가 if문 에서 읽기 왼쪽과 오른쪽 사이에서 값을 변경할 수 있습니다 .

다음은 짧은 데모입니다.

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

산출:

⋮
Ok
Ok
Ok
Ok
Ok
Ok
Ok
Ok
Not ok


답변

교체 된 줄을 읽을 수 있습니다.

double x = Double.NaN;

이로 인해 gotcha가 인쇄됩니다.

JLS (Java Language Specification)는 다음과 같이 말합니다.

부동 소수점 연산자는 예외를 생성하지 않습니다 (§11). 오버플로하는 연산은 부호있는 무한대를 생성하고 언더 플로하는 연산은 비정규 화 된 값 또는 부호있는 0을 생성하며, 수학적으로 명확한 결과가없는 연산은 NaN을 생성합니다. NaN을 피연산자로 사용하는 모든 숫자 연산은 결과로 NaN을 생성합니다. 이미 설명했듯이 NaN은 순서가 지정되지 않았으므로 하나 또는 두 개의 NaN을 포함하는 숫자 비교 연산은 false를 반환하고 NaN을 포함하는 모든! = 비교는 x가 NaN 일 때 x! = x를 포함하여 true를 반환합니다.


답변

나는 Gotcha!이것에서 얻을 수 있었다 .

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


답변

너무 많은 솔루션이 있습니다.

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