Java 증감 연산자, 하나의 표현식으로 확실하게 이해하기
Java의 증가 연산자(++)와 감소 연산자(--)는 변수의 값을 1씩 더하거나 빼는 단순한 연산자처럼 보이지만, 비교 연산자나 논리 연산자와 섞이면 결과를 예측하기 쉽지 않습니다. 이번 글에서는 다음 표현식을 예제로 삼아 연산자 우선순위와 평가 순서를 자세히 살펴보겠습니다.
int a = 2;
int b = 1;
boolean result = a > b || a != b && a == b++;
연산자 우선순위: &&가 ||보다 먼저 적용된다
Java에서 &&(논리곱) 연산자는 ||(논리합) 연산자보다 우선순위가 높습니다. 따라서 위 표현식은 다음과 같이 해석됩니다.
(a > b) || ((a != b) && (a == b++))
즉, a != b && a == b++ 부분이 하나의 그룹으로 묶인 뒤, 그 결과가 a > b와 함께 ||로 연결됩니다.
평가 결과: true, 그러나 a와 b는 변하지 않는다
a는 2, b는 1이므로 a > b는 참(true)입니다. 여기서 중요한 개념이 바로 || 연산자의 단락 평가(short-circuit evaluation)입니다. 왼쪽 피연산자가 이미 참이면 전체 결과가 참으로 확정되기 때문에, 오른쪽에 있는 a != b && a == b++는 아예 실행되지 않습니다.
만약 오른쪽 식이 평가된다고 가정해 보아도 a != b는 참이지만, a == b++는 2와 1을 비교하는 식이므로 거짓(false)입니다. 결국 이 부분은 거짓이 되고, 전체 표현식은 true || false로 참이 됩니다.
그리고 b++가 실제로 실행되지 않았기 때문에 최종적으로 a는 2, b는 1로 그대로 유지됩니다.
핵심 포인트: ==는 비교, =는 대입
많은 초보 개발자가 혼동하는 부분이 바로 여기입니다. a == b++에서 사용된 것은 대입 연산자 =가 아니라 관계(비교) 연산자 ==입니다. 따라서 이 식은 b++의 값을 a에 대입하는 것이 아니라, a와 b++의 값이 같은지 단순히 비교할 뿐입니다.
==: 두 값이 같은지 비교하는 관계 연산자=: 오른쪽 값을 왼쪽 변수에 저장하는 대입 연산자b++: 후위 증가 연산자로, 현재 값(1)을 먼저 사용한 뒤 b를 1 증가시킴
정리
이 예제에서 얻을 수 있는 교훈은 세 가지입니다. 첫째, &&가 ||보다 우선순위가 높다는 점. 둘째, ||와 &&는 단락 평가를 수행하므로 불필요한 오른쪽 식은 실행되지 않을 수 있다는 점. 셋째, ==는 비교 연산일 뿐 대입이 아니므로 변수 값이 변경되지 않는다는 점입니다. 복잡해 보이는 표현식도 우선순위와 평가 순서만 정확히 이해하면 결과를 쉽게 예측할 수 있습니다.