본문 바로가기

Java/Java SE, EE

[Java/Java SE, EE] 연산자(Operator)와 피연산자(Operand)

연산자(Operator)와 피연산자(Operand)

연산(Operation)은 데이터를 처리하여 결과를 산출하는 과정입니다. 연산자(Operator)는 연산에 필요한 기호를 의미하며, 피연산자(Operand)라고 부릅니다. 연산자와 피연산자를 이용하여 연산의 과정을 기술한 것을 연산식(Expressions)라고 합니다. 아래 코드에서 변수 a와 b는 연산식 c = a + b의 피연산자이며, +는 연산자입니다.

int a = 10;
int b = 20;
int c = a + b;

자바에서 제공하는 연산자의 종류는 다음과 같습니다.

구분 연산자 항의 개수 연산식 결과
산술 + 이항 두 피연산자의 합
산술 - 이항 두 피연산자의 차
산술 * 이항 두 피연산자의 곱
산술 / 이항 두 피연산자의 나누기
산술 % 이항 두 피연산자의 나머지
증감 ++ 또는 -- 단항 피연산자를 1만큼 증가 또는 1만큼 감소
부호 + 또는 - 단항 양수 또는 음수
논리 ! 단항 논리 부정(NOT), 피연산자가 true인 경우 false, 그 반대의 경우 true
논리 & 또는 && 이항 논리 곱(AND), 두 피연산자 모두 true인 경우 true
논리 | 또는 || 이항 논리 합(OR), 두 피연산자 중 하나라도 true인 경우 true, 모두 false인 경우 false
논리 ^ 이항 배타적 논리 합(XOR), 두 피연산자가 서로 다르면 true, 같으면 false
비트 논리 ~, &, |, ^ 단항, 이항 비트 부정(NOT), 비트 곱(AND), 비트 합(OR), 비트 배타적 논리 합(XOR)
비트 시프트 << 이항 피연산자의 비트를 좌측으로 다른 피연산자 만큼 이동
비트 시프트 >> 이항 피연산자의 비트를 우측으로 다른 피연산자 만큼 이동
비트 시프트 >>> 이항 피연산자의 비트를 우측으로 다른 피연산자 만큼 이동
대입 = 이항 피연산자의 값을 다른 피연산자에 대입
대입 +=, -=, *=, /=, %= 이항 두 피연산자의 합/차/곱/나누기/나머지 결과를 피연산자에 대입
대입 &=, |=, ^= 이항 두 피연산자의 논리 합, 논리 곱, 배타적 논리 합 결과를 피연산자에 대입
대입 <<=, >>=, >>>= 이항 두 피연산자의 비트 시프트 결과를 피연산자에 대입
문자열 + 이항 두 피연산자 문자열의 연결
조건 (조건식) ? A : B 삼항 조건식이 true인 경우 피연산자 A를 리턴, 그렇지 않은 경우 피연산자 B를 리턴

각각의 연산자에 대한 사용 방법과 설명에 대해서는 개별 문서로 다루도록 하겠습니다.

연산자 우선 순위와 연산 순서

연산자는 서로 다른 우선 순위를 갖습니다. 우선순위가 서로 다른 연산자 간에는 높은 우선 순위의 연산자가 먼저 처리됩니다. 예를 들면 수학에서와 같이 곱셈은 덧셈보다 먼저 계산됩니다.

int a = 10;
int b = 20;
int c = 30;
int d = a + b * c;    // a + (b * c) = 10 + (20 * 30) = 610

또한 동일한 연산자에 대해서는 왼쪽에서 오른쪽으로 계산하는 것이 보통입니다.

int a = 10;
int b = 20;
int c = 30;
int d = a + b + c;    // (a + b) + c = (10 + 20) + 30 = 60

예외적으로 단항 연산자(++, --, ~, !)와 대입 연산자(=, +=, ... 등)의 경우 동일한 연산자에 대해서 오른쪽에서 왼쪽으로 계산합니다.

int a, b, c, d;
int e = 10;

a = b = c = d = e;    // a = (b = (c = (d = e)))

다음은 각 연산자에 대한 우선 순위를 높은 순서부터 나열한 것입니다. 연산자 우선 순위에 대한 일반적인 규칙은 다음과 같이 정리 할 수 있습니다.

  • 단항, 이항, 삼항 연산자 순으로 높은 우선 순위를 갖습니다.
  • 산술, 비교, 논리, 조건, 대입 연산자 순으로 높은 우선 순위를 갖습니다.
연산자 우선 순위
증감(++, --), 부호(+, -), 비트 부정(~) 논리 부정(!) 매우 높음
산술(*, /, %) ...
산술(+, -)
비트 시프트(<<, >>, >>>)
비교(<, >, <=, >=, instanceof, ...)
비교(==, !=)
논리 곱(&)
배타적 논리 합(^)
논리 합(|)
논리 곱(&&)
논리 합(||)
조건(?:)
대입(=, +=, -=, *=, /=, %=, ^=, |=, <<=, >>=, >>>=) 매우 낮음

이러한 연산 순서는 단순한 계산 또는 적은 수의 피연산자를 사용하는 경우는 문제가 없습니다. 하지만 복잡한 수식을 프로그래밍 해야하는 경우, 각 피연산자의 연산 순서에 대해서 괄호 ()를 사용하여 강제 또는 의도대로 동작하도록 할 수 있습니다. 사실 모든 연산 순서를 기억하고 사용하는 것보다 피연산자의 종류가 많아지게 되면 속 편하게 괄호를 쓰는 것이 안전하고 가독성도 좋습니다.

int d = a + b * c;     // a + (b * c) = 610
int e = (a + b) * c;   // (a + b) * c = 900