We know it can in JavaScript.
But is it possible to print "Success" message on the condition given below in Java?
if (a==1 && a==2 && a==3) {
System.out.println("Success");
}
Someone suggested:
int _a = 1;
int a = 2;
int a_ = 3;
if (_a == 1 && a == 2 && a_ == 3) {
System.out.println("Success");
}
But by doing this we are changing the actual variable. Is there any other way?
The question is — Can (a==1 && a==2 && a==3) ever evaluate to true? The answer is — Yes.
It started with: Boolean type take only two literal values: true and false. These are distinct from numeric values, so true is not equal to 1, and false is not equal to 0. I know, that every type in JavaScript has a Boolean equivalent.
The equality operator ( == ) checks whether its two operands are equal, returning a Boolean result. Unlike the strict equality operator, it attempts to convert and compare operands that are of different types.
Yes, it's quite easy to achieve this with multiple threads, if you declare variable a
as volatile.
One thread constantly changes variable a from 1 to 3, and another thread constantly tests that a == 1 && a == 2 && a == 3
. It happens often enough to have a continuous stream of "Success" printed on the console.
(Note if you add an else {System.out.println("Failure");}
clause, you'll see that the test fails far more often than it succeeds.)
In practice, it also works without declaring a
as volatile, but only 21 times on my MacBook. Without volatile
, the compiler or HotSpot is allowed to cache a
or replace the if
statement with if (false)
. Most likely, HotSpot kicks in after a while and compiles it to assembly instructions that do cache the value of a
. With volatile
, it keeps printing "Success" forever.
public class VolatileRace {
private volatile int a;
public void start() {
new Thread(this::test).start();
new Thread(this::change).start();
}
public void test() {
while (true) {
if (a == 1 && a == 2 && a == 3) {
System.out.println("Success");
}
}
}
public void change() {
while (true) {
for (int i = 1; i < 4; i++) {
a = i;
}
}
}
public static void main(String[] args) {
new VolatileRace().start();
}
}
Using concepts (and code) from a brilliant code golf answer, Integer
values can be messed with.
In this case, it can make int
s casted to Integer
s be equal when they wouldn't normally be:
import java.lang.reflect.Field;
public class Test
{
public static void main(String[] args) throws Exception
{
Class cache = Integer.class.getDeclaredClasses()[0];
Field c = cache.getDeclaredField("cache");
c.setAccessible(true);
Integer[] array = (Integer[]) c.get(cache);
// array[129] is 1
array[130] = array[129]; // Set 2 to be 1
array[131] = array[129]; // Set 3 to be 1
Integer a = 1;
if(a == (Integer)1 && a == (Integer)2 && a == (Integer)3)
System.out.println("Success");
}
}
Unfortunately it's not quite as elegant as Erwin Bolwidt's multithreaded answer (as this one requires Integer
casting), but still some fun shenanigans take place.
In this question @aioobe suggests (and advise against) the use of C preprocessor for Java classes.
Although it is extremely cheaty, that's my solution:
#define a evil++
public class Main {
public static void main(String[] args) {
int evil = 1;
if (a==1 && a==2 && a==3)
System.out.println("Success");
}
}
If executed using the following commands it will output exactly one Success
:
cpp -P src/Main.java Main.java && javac Main.java && java Main
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With