programing

Java에서는 (a==1 & a==2 & a==3)가 true로 평가될 수 있습니까?

prostudy 2022. 6. 18. 09:15
반응형

Java에서는 (a==1 & a==2 & a==3)가 true로 평가될 수 있습니까?

JavaScript에서는 가능합니다.

그러나 Java에서 아래 조건을 조건으로 "Success" 메시지를 출력할 수 있습니까?

if (a==1 && a==2 && a==3) {
    System.out.println("Success");
}

어떤 분이 제안하셨습니다.

int _a = 1;
int a  = 2;
int a_ = 3;
if (_a == 1 && a == 2 && a_ == 3) {
    System.out.println("Success");
}

하지만 이렇게 함으로써 실제 변수를 변경할 수 있습니다.다른 방법은 없습니까?

여러 스레드를 ,, 변, 변, 변, 변, 변, 변, 변, yes, yes, yes, yes, yes, yes, ,, yes, yes, yes, ,, ,, ,, ,, ,, ,, ,, ,, ,, variable, variable, variable, variable, variable, variable, variable, variable, variable variable, ,a휘발성이 있습니다.

3으로 하고, 는 1에서 3으로 계속 합니다.a == 1 && a == 2 && a == 3콘솔에 "Success" 스트림이 계속 표시될 정도로 자주 발생합니다.

(「」:( 「」)를 else {System.out.println("Failure");}이 조항은 테스트가 성공하는 것보다 실패하는 경우가 훨씬 많다는 것을 알게 될 것입니다.)

선언을 하지 합니다.a21일, ,일단,일단,일단,일단,일단,일단없음.volatile은 HotSpot을 수 a '바꿔주세요'를 바꿉니다.if「」가 붙은 .if (false)되어 "HotSpot", "HotSpot", "HotSpot", "HotSpot", "HotSpot", "HotSpot", "HotSpot"의 명령에 a. 함께 volatile이치노

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

훌륭한 코드 골프 답변의 컨셉(및 코드)을 사용하여Integer값을 조작할 수 있습니다.

「 」, 「 」로 할 수 있습니다.int 캐스팅되다Integer 경우 과 같습니다.s는 다음과 같습니다.

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

불행하게도 이것은 Erwin Bolwidt의 멀티 스레드화된 대답만큼 우아하지는 않지만(이것은 캐스팅이 필요하기 때문에), 몇 가지 재미있는 셰나니건이 여전히 일어나고 있다.

질문에서 @aioobe는 Java 클래스에 C 프리프로세서를 사용할 것을 제안합니다(또한 권장하지 않습니다).

비록 매우 사기적이지만, 그것이 나의 해결책이다.

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

다음 명령을 사용하여 실행할 경우 정확히 1개의 명령어를 출력합니다.Success:

cpp -P src/Main.java Main.java && javac Main.java && java Main

Erwin Bolwidtphflack의 훌륭한 답변 덕분에 이 코드를 사실로 평가할 수 있다는 것을 이미 알고 있기 때문에, 질문에서 제시된 것과 같은 상황에 대처할 때 매우 주의를 기울일 필요가 있음을 보여 주고 싶었습니다.때로는 보이는 것이 당신이 생각하는 것과 다를 수 있기 때문입니다.

은 이 가 인쇄된다는 입니다.Success!콘솔로 이동합니다.내가 사기를 좀 쳤다는알지만, 난 여전히 여기가 바로 여기서 발표하기에 좋은 장소라고 생각해.

이와 같은 코드를 작성하는 목적이 무엇이든 간에 다음 상황에 어떻게 대처해야 하는지, 그리고 자신이 생각하는 것이 틀리지 않은지 확인하는 것이 좋습니다.

나는 라틴어 a와 구별되는 문자인 키릴 문자 a를 사용했다.여기서 if 문장에서 사용되는 문자를 검사할 수 있습니다.

이것은 변수의 이름이 다른 알파벳에서 따왔기 때문에 작동합니다.이들은 서로 다른 값을 가진 두 개의 서로 다른 변수를 생성하는 고유한 식별자입니다.

이 코드를 올바르게 동작시키려면 문자 인코딩을 양쪽 문자를 모두 지원하는 것으로 변경해야 합니다.예를 들어 모든 Unicode 인코딩(UTF-8, UTF-16(BE 또는 LE), UTF-32, 심지어 UTF-7), Windows-1251, ISO 885-9, KO-8THANK 등입니다.

public class A {
    public static void main(String[] args) {
        int а = 0;
        int a = 1;
        if(а == 0 && a == 1) {
            System.out.println("Success!");
        }
    }
}

(앞으로 그런 문제에 대처할 필요가 없기를 바랍니다.)

PowerMock의 파워를 사용하여 (앞서 설명한 휘발성 데이터 레이싱 접근법 외에) 이 접근법에 접근하는 다른 방법이 있습니다.PowerMock을 사용하면 메서드를 다른 구현으로 대체할 수 있습니다.언박스와 은 「」입니다.(a == 1 && a == 2 && a == 3)을 사용하다

@은 @phflack Java를 Integer.valueOf(...) 언박스를 으로써 자동 를 변경합니다.Integer.intValue()discl.discl.discl을 클릭합니다.

아래 접근방식의 장점은 질문의 OP에 의해 주어진 원래의 if-statement를 변경하지 않고 사용할 수 있다는 것입니다.이것이 가장 우아하다고 생각합니다.

import static org.powermock.api.support.membermodification.MemberMatcher.method;
import static org.powermock.api.support.membermodification.MemberModifier.replace;

import java.util.concurrent.atomic.AtomicInteger;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@PrepareForTest(Integer.class)
@RunWith(PowerMockRunner.class)
public class Ais123 {
    @Before
    public void before() {
        // "value" is just a place to store an incrementing integer
        AtomicInteger value = new AtomicInteger(1);
        replace(method(Integer.class, "intValue"))
            .with((proxy, method, args) -> value.getAndIncrement());
    }

    @Test
    public void test() {
        Integer a = 1;

        if (a == 1 && a == 2 && a == 3) {
            System.out.println("Success");
        } else {
            Assert.fail("(a == 1 && a == 2 && a == 3) != true, a = " + a.intValue());
        }
    }

}

이것은 이 JavaScript 질문의 후속인 것 같기 때문에, 이 트릭과 유사한 트릭이 자바에서도 기능하는 에 주의할 필요가 있습니다.

public class Q48383521 {
    public static void main(String[] args) {
        int aᅠ = 1;
        int ᅠ2 = 3;
        int a = 3;
        if(aᅠ==1 && a==ᅠ2 && a==3) {
            System.out.println("success");
        }
    }
}

IDEONE에서


하지만 이것이 Unicode로 할 수 있는 최악의 일은 아닙니다.유효한 식별자 부분인 공백 문자 또는 제어 문자를 사용하거나 동일한 모양의 다른 문자를 사용해도 서로 다른 식별자가 생성되고 텍스트 검색을 수행할 때 확인할 수 있습니다.

근데 이 프로그램은

public class Q48383521 {
    public static void main(String[] args) {
        int ä = 1;
        int ä = 2;
        if(ä == 1 && ä == 2) {
            System.out.println("success");
        }
    }
}

는 적어도 Unicode 관점에서 동일한2개의 식별자를 사용합니다. 글자를 다른 할 수 .ä,사용.U+00E4그리고.U+0061 U+0308.

IDEONE에서

따라서 사용하는 도구에 따라서는 동일한 모양일 뿐만 아니라 Unicode 지원 텍스트 도구도 차이를 보고하지 않을 수 있습니다. 검색 시 항상 두 가지 모두를 찾을 수 있습니다.소스코드를 다른 사람에게 카피하면, 다른 표현이 없어져, 헬퍼가 「이상한 동작」을 재현할 수 없게 되는 문제도 있습니다.

@erwin의 훌륭한 답변에 영감을 받아 비슷한 예를 썼지만 Java Stream API를 사용했습니다.

흥미로운 점은 이 솔루션이 효과가 있다는 것입니다만, 매우 드문 경우입니다.just-in-time컴파일러는 이러한 코드를 최적화합니다).

이 트릭은, 다음의 어느쪽인가를 무효로 하는 것입니다.JIT다음을 사용한 최적화VM옵션:

-Djava.compiler=NONE

이 상황에서는 성공 사례가 크게 증가합니다.코드는 다음과 같습니다.

class Race {
    private static int a;

    public static void main(String[] args) {
        IntStream.range(0, 100_000).parallel().forEach(i -> {
            a = 1;
            a = 2;
            a = 3;
            testValue();
        });
    }

    private static void testValue() {
        if (a == 1 && a == 2 && a == 3) {
            System.out.println("Success");
        }
    }
}

추신: 병렬 스트림은 후드 아래에서 사용되며 변수 a는 동기화 없이 여러 스레드 간에 공유되므로 결과가 결정적이지 않습니다.

유사한 선을 따라 플로트(또는 더블)가 분할(또는 곱셈)을 통해 많은 수로 언더플로(또는 오버플로)하도록 강제함으로써 다음을 수행합니다.

int a = 1;
if (a / Float.POSITIVE_INFINITY == 1 / Float.POSITIVE_INFINITY
        && a / Float.POSITIVE_INFINITY == 2 / Float.POSITIVE_INFINITY
        && a / Float.POSITIVE_INFINITY == 3 / Float.POSITIVE_INFINITY) {
    System.out.println("Success");
}

언급URL : https://stackoverflow.com/questions/48383521/can-a-1-a-2-a-3-evaluate-to-true-in-java

반응형