수학에서 1 + 2 * 3
의 연산 결과는 무엇일까? 덧셈보다 곱셈이 우선순위가 더 높다. 따라서 다음과 같이 계산한다.
1 + (2 * 3) // 곱셈(*)이 연산자 우선순위가 높다. 따라서 먼저 계산한다.
1 + 6
7 // 결과
package operator;
public class Operator3 {
public static void main(String[] args) {
int sum1 = 1 + 2 * 3; // 1 + (2 * 3)
int sum2 = (1 + 2) * 3;
System.out.println("sum1 = " + sum1); // sum1 = 7
System.out.println("sum2 = " + sum2); // sum2 = 9
}
}
sum1 = 7
이 나왔다. 연산자 우선순위에 의해 곱셈이 먼저 계산된 것이다.()
를 사용하면 된다. ()
를 사용한 곳이 먼저 계산된다.sum2
는 괄호를 사용해서 덧셈이 먼저 처리되도록 했다.(1 + 2) * 3
3 * 3
9
package operator;
public class Operator4 {
public static void main(String[] args) {
int sum3 = 2 * 2 + 3 * 3; // (2 * 2) + (3 * 3)
int sum4 = (2 * 2) + (3 * 3); // sum3과 같다.
System.out.println("sum3 = " + sum3); // sum3 = 13
System.out.println("sum4 = " + sum4); // sum4 = 13
}
}
sum3
, sum4
에 저장하는 두 연산은 같은 연산이다. 그런데 괄호가 없는 2 * 2 + 3 * 3
연산은 평소 수학을 잘 하는 분들은 금방 풀겠지만 보통은 이 연산을 보고 잠깐 연산자 우선순위를 생각을 해야한다.
2 * 2 + 3 * 3
(2 * 2) + (3 * 3) // 곱셈이 우선순위가 높다
4 + 9
13
이렇게 복잡한 경우 sum4
의 (2 * 2) + (3 * 3)
와 같이 괄호를 명시적으로 사용하는 것이 더 명확하고 이해하기 쉽다.
코드를 몇자 줄여서 모호하거나 복잡해 지는 것 보다는 코드가 더 많더라도 명확하고 단순한 것이 더 유지보수하기 좋다.
연산자 우선순위가 애매하거나 조금이라도 복잡하다면 언제나 괄호를 고려하자.
자바는 다음과 같은 연산자 우선순위가 있다. 높은 것에서 낮은 순으로 적었다. 처음에 나오는 괄호()
가 우선순위가 가장 높고, 마지막의 대입 연산자(=
)가 우선순위가 가장 낮다.
()
++
, --
, !
, ~
, new
, (type)
)*
, /
, %
우선, 그 다음에 +
, -
)<<
, >>
, >>>
)<
, <=
, >
, >=
, instanceof
)==
, !=
)&
, ^
, |
)&&
, ||
)? :
)=
, +=
, -=
, *=
, /=
, %=
, …)그러면 이 많은 우선순위를 어떻게 외워야 할까? 사실 대부분의 실무 개발자들은 연산자 우선순위를 외우지 않는다. 연산자 우선순위는 딱 2가지만 기억하면 된다.
우선순위는 상식선에서 생각하면 대부분 문제가 없다.
다음 예를 보자.
int sum = 1 + 2 * 3
당연히 +
보다 *
이 우선순위가 높다.
다음으로 산술 연산자(+
)와 대입 연산자(=
)를 비교하는 예를 보자.
int sum = 1 + 2
int sum = 1 + 2
int sum = 3 // 산술 연산자가 먼저 처리된다.
sum = 3 // 대입 연산자가 마지막에 처리된다.
1 + 2
를 먼저 처리한 다음에 그 결과 값을 변수 sum
에 넣어야 한다. 대입 연산자인 =
이 먼저 수행된다고 생각하기가 사실 더 어렵다.코드를 딱 보았을 때 연산자 우선순위를 고민해야 할 것 같으면, 그러니까 뭔가 복잡해보이면 나 뿐만 아니라 모든 사람이 그렇게 느낀다. 이때는 다음과 같이 괄호를 사용해서 우선순위를 명시적으로 지정하면 된다.
((2 * 2) + (3 * 3)) / (3 + 2)