program tip

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

radiobox 2020. 8. 8. 12:17
반응형

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;

This would cause the gotcha to be printed.

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

Floating-point operators produce no exceptions (§11). An operation that overflows produces a signed infinity, an operation that underflows produces a denormalized value or a signed zero, and an operation that has no mathematically definite result produces NaN. All numeric operations with NaN as an operand produce NaN as a result. As has already been described, NaN is unordered, so a numeric comparison operation involving one or two NaNs returns false and any != comparison involving NaN returns true, including x!=x when x is NaN.


I managed to get a Gotcha! from this:

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

There are so many 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");
        }
    }
}

One easy solution is:

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

But I don't know all the rules to this riddle...

:) I know that this is a cheat, but without knowing all rules, is this the easiest solution to the question :)


Create your own class System in tha same package with Condition.
In this case your System class will hide java.lang.System class

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


Using the same skip/change output approach from another answers:

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

참고URL : https://stackoverflow.com/questions/19416644/how-can-a-java-variable-be-different-from-itself

반응형