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) ?

10195 次浏览

One simple way is to use Float.NaN:

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


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

You can do the same with Double.NaN.


From JLS §15.21.1. Numerical Equality Operators ABC0 and !=:

Floating-point equality testing is performed in accordance with the rules of the IEEE 754 standard:

  • If either operand is NaN, then the result of == is false but the result of != is true.

    Indeed, the test x!=x is true if and only if the value of x is NaN.

...

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

Not sure if this is an option but changing x from local variable to a field would allow other thread to change its value between the reading left and right side in if statement.

Here is short demo:

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

Output:

⋮
Ok
Ok
Ok
Ok
Ok
Ok
Ok
Ok
Not ok

There are so many solutions:

import java.io.PrintStream;


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

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

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

By the Java Language Specifications NaN is not equal to NaN.

Therefore any line that caused x to be equal to NaN would cause this, such as

double x=Math.sqrt(-1);

From the Java Language Specifications:

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.

The replaced line could read.

double x = Double.NaN;

This would cause the gotcha to be printed.

Java Language Specification (JLS) says:

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.

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 :)

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