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


106

이 질문을 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로 설정) 어떻게해야합니까?


12
더 많은 제한이 있어야한다고 생각합니다. 그렇지 않으면 너무 개방적입니다.
페르마의 리틀 학생

52
System.out.println("Gotcha!");댓글 대신에 간단 합니까? :)
stuXnet 2013

7
좋은, 두 번 A = Double.NaN의 짧은 대답은 내 "해킹은 속임수입니다)
기독교 Kuetbach

47
이것은 귀여운 자바 퀴즈이지만 아무도 인터뷰 질문으로 생각하지 않기를 바랍니다. 구직자를 고려하는 사람들은 그가 얼마나 많은 퀴즈를 쌓았는지가 아니라 후보자가 프로그래밍을 이해하는지 파악하기 위해 최선을 다해야합니다. 나는 자바 프로그래밍에서 17 년 동안 부동 소수점 숫자를 거의 사용하지 않았고, NaN 구조는 훨씬 적었고, == 연산자로 어떻게 작동하는지 훨씬 덜 알았습니다 ...
arcy

8
@ user1158692 의견 물질, 나는 개인적으로 기본 운영자가 오버라이드 (override)되어있는 모든 프로그램을 미워하고 내가 자바받을 코드는 내가 본 (※로 오버라이드 (override)로 엉망이되어 있지 않은 것을 기쁘게 생각 벡터 외적내적 때문에 둘 다 벡터 곱셈의 종류입니다. 격분합니다! 반면 자바에서는 하나가 호출 .cross()되고 다른 하나는 .dot()혼란스럽지 않습니다. 또한 "== 연산자를 무시하고 항상 false를 반환"할 수 없다는 사실은 pro java
Richard Tingle

답변:


172

한 가지 간단한 방법은 다음을 사용하는 것입니다 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 인 경우에만 수행됩니다 .

...


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

63
헤, 이것은 질문에 완전히 대답합니다.
Dave Newton

5
@AswinMurugesh 맞습니다.하지만이 대답처럼 완전히 문자 그대로 질문을 받아들이면 else모두 삭제할 수 있습니다 . 이것은 기술적으로 질문의 조건을 위반하지 않습니다.
arshajii

67
이것이 두 번째로 높은 투표를받은 대답이라는 점을 고려할 때, 내가 매우 웃기거나 엉뚱한 프로그래머라고 결론을 내릴지 모르겠습니다.
Jeroen Vannevel 2013 년

5
@JeroenVannevel 요구 사항을 감안할 때 이것이 가장 KISS / YAGNI / 적절한 답변이라고 생각합니다;)
Izkata

12
@jddsantaella : 분명히 이것은 나중에 편집되었습니다. 원래 질문은 "어떻게 'not ok'를 인쇄 할 수 있습니까?"라고했습니다.
Jeroen Vannevel 2013 년

147

에 의해 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를 반환합니다.


@ sᴜʀᴇsʜᴀᴛᴛᴀ 공정한 요점입니다. "코딩 규칙"이라는 말을 찾기 위해 너무 바빴 기 때문에 실제로 질문에 대답하는 것을 잊었습니다
Richard Tingle

a가 Object 또는 double로 선언 된 경우에만 유효합니다.
Christian Kuetbach 2013

1
@ChristianKuetbach 사실은, 반대로 정보의 부재에서 I 주석 처리 된 라인은 아무것도 할 수 있습니다 가정 한
리처드 설렘

2
내 속임수도 정확하고 규칙을 충족합니다. 나는 if- 문 앞에만 편집했고 "Gotcha! 만 인쇄되었습니다.이 대답은이 수수께끼를 만든 사람의 마음에있는 대답이 아니라고 확신합니다. 그러나 수수께끼는 잘 정의되어 있지 않습니다 (대부분의 소프트웨어 프로젝트처럼 ).
기독교 Kuetbach

73

이것이 옵션인지 확실하지 않지만 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

8
Haha +1은 노력했지만, 자바 연구실의 누구도 이와 같은 것을 생각 해낼 수 없었습니다 (강사 포함).
William Gaul

28
@WilliamGaul 정말? 나는 항상 그것이 멀티 스레딩의 가능한 문제를 보여주는 기본적인 예 중 하나이며 왜이 주제가 쉽다고 생각하는 사람들은 어떤 것도
책임지지

4
나는 당신의 대답을 읽을 때 까지이 문제에 대해 생각조차하지 않았습니다. : 내 정신 툴킷이 추가 주셔서 감사합니다
베히

56

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

double x = Double.NaN;

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

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

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


또는 a가 String으로 선언되면 컴파일 오류가 발생합니다. a = "Nope"; 나는 'A'의 유형을 요청하는 이유
기독교 Kuetbach

위의 코드는 유형에 대한 정보를 제공하지 않으므로 a가 아직 정의되지 않았다고 가정했습니다.
Mex

당신의 대답은 수수께끼 제작자의 마음에 있던 대답이라고 생각합니다. 그러나 규칙은 명확하지 않았습니다. 오직 두 가지 규칙이 주어졌다 : 1 만 코멘트와 함께 라인에 삽입하고 2 단 하나 "잡았다가 인쇄된다!.
기독교 Kuetbach에게

수수께끼 작성자는 {}
Mex

30

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

1
이것은 질문이 요구하는 코멘트보다 더 많이 변경됩니다.
Mex

그런 식으로 해봤지만 항상 똑같은 결과가 나올 거라고 확신하는 것 같지 않나요?
AndreDurao 2013

4
@Mex-실제로 수행하지만 때로는 a != a다른 스레드에 의해 변경 되었기 때문에 추가 요점을 보여주기 위해 원본을 충분히 보존 합니다. 나는 이것이 인터뷰에서 점수를 얻을 것이라고 생각합니다.
OldCurmudgeon 2013

이것은 내가 그 "희망"으로이 작품을 가정, 실제로는 매우 영리한 생각입니다 a비교를 위해 제 1 및 제 2 액세스 사이 - 첫 번째 스레드에 의해 변경된다
리처드 설렘을

4
당신의 의심 자들이 되십시오. 필요한 경우 핵심 if문장 위에 작성한 모든 내용을 끔찍한 한 줄로 작성할 수 있다는 점에 주목할 가치가 있습니다.
리처드 설렘

25

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

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

1
내가 뭔가를 놓치고 있지 않다면 그것은 super.println"불량"이어야합니다. 맞죠?
Izkata

@Izkata 예, 원하는 출력이 무엇인지 다시 확인하지 않았습니다.
Johannes Kuhn

2
정말 훌륭합니다!
Dariusz

25

쉬운 해결책은 다음과 같습니다.

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

하지만이 수수께끼의 모든 규칙을 모르겠습니다 ...

:) 이것이 속임수라는 것을 알고 있지만 모든 규칙을 알지 못하면 이것이 질문에 대한 가장 쉬운 해결책입니다 :)


1
한 줄에 쓸 수)
기독교 Kuetbach

6
@ChristianKuetbach 모든 프로그램과 마찬가지로
Richard Tingle

2
이 같은 사실은 프로그램에 시도하는 경우 @ChristianKuetbach는 공평 컴파일러는 즉시 컴퓨터에있는 모든 파일을 삭제해야합니다
리처드 설렘

1
왜 그렇게 어렵게 만들까요? if (System.out.println("Gotcha") && false)
알렉시스

3
오류 : (에서 System.out.println ( "잡았다") && false)를 컴파일되지 않습니다 귀하의 코드 ... 만약 여기 허용 '무효'유형이 아닌
기독교 Kuetbach

11

자신의 클래스를 작성 System과 함께 그쪽으로 같은 패키지에 Condition.
이 경우 귀하의 System클래스는 숨길 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");
        }
    }
}  

이데온 데모


9

다른 답변에서 동일한 건너 뛰기 / 변경 출력 접근 방식 사용 :

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");
        }
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.