2017-10-29 2 views
0

에서 (+ =, =, * =, ...는) 다음 코드의 결과에 대해 조금 혼란 스러워요 :혼란 자바

int x = 1; 
    x -= ((x += 1) << 1); 
    System.out.println(x); 

그것은 -3를 출력하지만,

| Opearation | Returned | x | 
+------------+----------+---+ 
| int x = 1; |  - | 1 | 
+------------+----------+---+ 
| (x += 1) |  2 | 2 | 
+------------+----------+---+ 
| (2 << 1) |  4 | 2 | 
+------------+----------+---+ 
| x -= 4; |  - |-2 | 

을 나는 여기에 놓치고 무엇 : 내 머리 속에서 계산은 다음과 같이 가야 있기 때문에, -2를 인쇄 할 것으로 예상거야? 누군가 제발 나에게 무슨 일이 일어나는지 설명해 줄 수 있니?

감사합니다.

먼저 왼쪽 피연산자가 평가된다 : 왼쪽 피연산자 식은 다음 배열 액세스 식 없으면

+0

잘 정의 된 것으로 가정하면 JLS의 관점에서 대답해야 할 것입니다. 그러나 이처럼 이국적인 표현은 실용적인 목적을 제공하지 못합니다. – HuStmpHrrr

답변

3

JLS 15.26.2은 https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.26.2

, 다음 말한다 변수를 생성합니다. 이 평가가 갑자기 완료되면 할당 표현식이 같은 이유로 갑자기 완료됩니다. 오른쪽 피연산자는 평가되지 않고 할당이 발생하지 않습니다.

그렇지 않으면 왼쪽 피연산자의 값이 저장되고 오른쪽 피연산자가 계산됩니다. 이 평가가 갑자기 완료되면 동일한 이유로 할당 표현식이 갑자기 완료되고 할당이 발생하지 않습니다.

그렇지 않으면 왼쪽 변수의 저장된 값과 오른쪽 피연산자의 값을 사용하여 복합 할당 연산자가 나타내는 이진 연산을 수행합니다. 이 작업이 갑자기 완료되면 같은 이유로 할당식이 갑자기 완료되고 할당이 수행되지 않습니다.

그렇지 않으면 이진 연산의 결과가 값 세트 변환 (§5.1.13)에서 해당 표준 값 세트 (확장 지수 값 세트가 아님)로 종속 된 왼쪽 변수의 유형으로 변환됩니다. 변환 결과는 변수에 저장됩니다.

따라서 x의 원래 값, 즉 1이 저장되면 RHS가 평가됩니다. 따라서 -3입니다.

+0

감사합니다. 이제 나에게 무슨 일이 일어나는지 분명하다. – txmns

-1
x -= ((x += 1) << 1); 
x = x - ((x += 1) << 1); 
    = 1 - ((1 + 1) << 1); 
    = 1 - (2 << 1) 
    = 1 - 4 
    = -3 
0

하위 표현식 (x + = 1)이 처리되기 전에 표현식의 RHS에 값이 채워 지므로 가장 왼쪽 x가 x + = 1에서 처리되기 전에 1 방향으로 대체됩니다. 따라서 ...

x = 1 - ((x=1+1) << 1) 
x = 1 - ((x=2) << 1) 
x = 1 - (2 << 1) 
x = 1 - 4 
x = -3 

여기서 x = 2는 할당 연산자가 변수에 할당 된 것과 동일한 값을 반환하기 때문에 결과는 2입니다. 다른 언어와는 달리

0

(당신을 찾고, C++), Java 언어 사양 보장 expression operands are evaluated left-to-right 그 :

사업자의 피연산자가 특정 평가 순서대로 평가 한 것으로 나타났습니다한다는 Java 프로그램 언어의 보장, 즉, 왼쪽에서 오른쪽으로.

의이 복합 명령문을 풀다 보자

x -= ((x += 1) << 1); 
x = x - ((x = x + 1) << 1); 
    ^

나중에 표현 내에서 일어나는 할당 (이 경우 값에 영향을 미치지 않음을 의미 먼저 평가 화살표, 함께 x, JVM 스택에는 이미 1이 있습니다. 나머지 평가는 예상대로 진행되지만 최종 작업은 1 - 4 = -3입니다. 절대적으로 여기에 적용 바로 위의 문 후 JLS는 메모를 포함

참고 : 그 코드가이 규격에 결정적으로 의존하지 않는 것이 좋습니다

. 코드는 각 표현식에 부작용이 많지 않은 경우, 가장 바깥 쪽 연산 인 경우 및 표현식의 왼쪽에서 오른쪽으로 평가 한 결과로 예외가 발생하는 코드에 정확히 의존하지 않는 경우에 더 명확합니다.

+0

@txmns 도와 드리겠습니다. 도움이되는 답변을 찾으면 왼쪽 화살표를 사용하여 응답을 upvote 할 수 있습니다. 유용하다고 생각하는만큼 많은 대답을 upvote 할 수 있습니다. "동의"버튼을 찾은 것을 보았습니다.이 버튼은 가장 좋거나 가장 도움이되었다고 생각하는 답변입니다. – chrylis