본문으로 건너뛰기

Ch 3.1 연산자(Operator) 기초

프로그램에서 데이터를 가공하고 계산하기 위해 사용되는 기호를 연산자(Operator) 라고 합니다. 자바는 수학적 계산, 논리적 판단 등을 위한 다양한 연산자를 제공합니다. 이 챕터에서는 연산자의 개념, 분류, 우선순위, 결합 방향을 체계적으로 정리합니다.


1. 연산자와 피연산자

  • 연산자(Operator): 연산을 수행하는 기호 (예: +, -, *, /, =)
  • 피연산자(Operand): 연산자의 작업 대상 (변수, 상수, 리터럴, 수식)
int result = x + 3;
// 연산자: = , +
// 피연산자: result, x, 3

연산자는 피연산자로 연산을 수행한 후 항상 결과값(Result) 을 반환합니다. 그 결과값은 변수에 저장하거나 다른 연산의 피연산자로 사용할 수 있습니다.

public class OperatorBasic {
public static void main(String[] args) {
int x = 10;
int y = 3;

// + 연산자: x와 y를 더한 결과(13)를 sum에 저장
int sum = x + y;

// * 연산자: sum과 2를 곱한 결과(26)를 product에 저장
int product = sum * 2;

// == 연산자: x와 10이 같은지 비교한 결과(true)를 isEqual에 저장
boolean isEqual = (x == 10);

System.out.println("sum = " + sum); // 13
System.out.println("product = " + product); // 26
System.out.println("isEqual = " + isEqual); // true
}
}

2. 연산자의 분류

자바의 연산자는 피연산자의 개수 에 따라 세 가지로 분류할 수 있습니다.

분류설명예시
단항 연산자 (Unary)피연산자가 1개++i, --i, -x, !flag
이항 연산자 (Binary)피연산자가 2개a + b, x > y, a && b
삼항 연산자 (Ternary)피연산자가 3개조건 ? 참값 : 거짓값

또한 기능 에 따라 다음과 같이 분류할 수 있습니다.

종류연산자설명
산술 연산자+, -, *, /, %사칙연산 및 나머지
비교 연산자==, !=, >, <, >=, <=크기 및 동등 비교, 결과는 boolean
논리 연산자&&, ||, !, ^논리 AND, OR, NOT, XOR
대입 연산자=, +=, -=, *=, /=, %=우변 값을 좌변 변수에 저장
비트 연산자&, |, ^, ~, <<, >>, >>>이진수 비트 단위 연산
조건 연산자? :삼항 연산자, 조건에 따라 값 선택
기타instanceof, ->, ::타입 확인, 람다, 메서드 참조

3. 연산자 우선순위(Precedence)

식에 여러 연산자가 섞여 있을 때, 어느 연산자를 먼저 처리할지 결정 하는 규칙입니다. 수학의 사칙연산 우선순위(*+보다 먼저)와 유사합니다.

아래 표는 우선순위가 높은 것부터 낮은 순 으로 정리한 것입니다.

우선순위연산자결합 방향설명
1 (최고)(), [], .좌 → 우괄호, 배열 접근, 멤버 접근
2++, -- (후위)좌 → 우후위 증감
3++, -- (전위), +, -, ~, !우 → 좌전위 증감, 단항 부호, 비트 NOT, 논리 NOT
4*, /, %좌 → 우곱셈, 나눗셈, 나머지
5+, -좌 → 우덧셈, 뺄셈
6<<, >>, >>>좌 → 우비트 시프트
7<, >, <=, >=, instanceof좌 → 우대소 비교, 타입 확인
8==, !=좌 → 우동등 비교
9&좌 → 우비트 AND
10^좌 → 우비트 XOR
11|좌 → 우비트 OR
12&&좌 → 우논리 AND
13||좌 → 우논리 OR
14? :우 → 좌삼항(조건) 연산자
15 (최저)=, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>=우 → 좌대입 연산자
public class Precedence {
public static void main(String[] args) {
// * 가 + 보다 우선순위가 높으므로 먼저 계산됨
int result1 = 2 + 3 * 4; // 2 + 12 = 14
System.out.println(result1); // 14

// 괄호로 우선순위를 직접 지정
int result2 = (2 + 3) * 4; // 5 * 4 = 20
System.out.println(result2); // 20

// 비교 연산자가 논리 연산자보다 우선순위가 높음
boolean check = 5 > 3 && 10 < 20; // (5>3) && (10<20) = true && true = true
System.out.println(check); // true
}
}
우선순위가 헷갈릴 때는 괄호를 사용하세요

우선순위 표를 외우려 하지 않아도 됩니다. 복잡한 식에서는 괄호 ()를 사용해 우선순위를 직접 명시 하는 것이 가독성도 높이고 버그도 줄이는 좋은 습관입니다.


4. 결합 방향(Associativity)

우선순위가 동일한 연산자 가 여러 개 나올 때, 왼쪽부터 처리할지 오른쪽부터 처리할지를 결정하는 규칙입니다.

좌결합(Left-to-Right)

대부분의 이항 연산자는 왼쪽에서 오른쪽으로 처리됩니다.

// 좌결합 예시: - 연산자
int a = 10 - 3 - 2;
// (10 - 3) - 2 = 7 - 2 = 5 (왼쪽부터)
System.out.println(a); // 5

// 좌결합 예시: / 연산자
int b = 24 / 4 / 2;
// (24 / 4) / 2 = 6 / 2 = 3 (왼쪽부터)
System.out.println(b); // 3

우결합(Right-to-Left)

단항 연산자, 대입 연산자, 삼항 연산자는 오른쪽에서 왼쪽으로 처리됩니다.

// 우결합 예시: 대입 연산자 =
int x, y, z;
x = y = z = 10;
// z = 10 → y = 10 → x = 10 (오른쪽부터)
System.out.println(x + ", " + y + ", " + z); // 10, 10, 10

// 우결합 예시: 전위 단항 연산자
int n = 5;
int result = -(-n); // -(-(5)) = -(-5) = 5
System.out.println(result); // 5

5. 대입 연산자와 복합 대입 연산자

단순 대입 연산자 (=)

우변(오른쪽)의 값을 좌변(왼쪽) 변수에 저장합니다. 자바에서 가장 빈번하게 사용되는 연산자입니다.

int score = 100;       // 100을 score에 저장
String name = "Alice"; // "Alice"를 name에 저장
boolean pass = true; // true를 pass에 저장

복합 대입 연산자 (Compound Assignment)

산술 연산 + 대입을 한 번에 처리하는 축약 표현입니다.

복합 대입풀어쓴 표현설명
a += ba = a + ba에 b를 더한 값을 a에 저장
a -= ba = a - ba에서 b를 뺀 값을 a에 저장
a *= ba = a * ba와 b를 곱한 값을 a에 저장
a /= ba = a / ba를 b로 나눈 값을 a에 저장
a %= ba = a % ba를 b로 나눈 나머지를 a에 저장
a &= ba = a & b비트 AND 후 a에 저장
a |= ba = a | b비트 OR 후 a에 저장
a ^= ba = a ^ b비트 XOR 후 a에 저장
a <<= ba = a << b왼쪽 시프트 후 a에 저장
a >>= ba = a >> b오른쪽 시프트 후 a에 저장
public class CompoundAssignment {
public static void main(String[] args) {
int score = 80;

score += 10; // score = score + 10 = 90
System.out.println("+=: " + score); // 90

score -= 5; // score = score - 5 = 85
System.out.println("-=: " + score); // 85

score *= 2; // score = score * 2 = 170
System.out.println("*=: " + score); // 170

score /= 4; // score = score / 4 = 42 (정수 나눗셈, 소수점 버림)
System.out.println("/=: " + score); // 42

score %= 10; // score = score % 10 = 2
System.out.println("%=: " + score); // 2
}
}
복합 대입 연산자의 내부 형변환

복합 대입 연산자는 내부적으로 자동 형변환(묵시적 캐스팅) 을 수행합니다.

byte b = 10;
// b = b + 5; // 컴파일 에러! b+5의 결과는 int이므로 byte에 바로 대입 불가
b += 5; // 정상 동작! 내부적으로 b = (byte)(b + 5) 로 처리됨
System.out.println(b); // 15

단순 대입에서는 명시적 캐스팅이 필요한 경우라도, 복합 대입 연산자는 자동으로 처리해 줍니다.


6. 연산자 우선순위 실수 예제와 괄호 권장

우선순위를 잘못 이해하면 예상치 못한 결과가 나올 수 있습니다.

public class PrecedenceTrap {
public static void main(String[] args) {
// 함정 예시 1: + 와 * 의 우선순위
int a = 1 + 2 * 3; // 1 + (2*3) = 1 + 6 = 7 (의도가 7이면 OK)
int b = (1 + 2) * 3; // (1+2) * 3 = 3 * 3 = 9 (의도가 9이면 괄호 필수)
System.out.println("a = " + a); // 7
System.out.println("b = " + b); // 9

// 함정 예시 2: 비트 연산자와 비교 연산자
// & 의 우선순위는 == 보다 낮음!
int flags = 0b0110;
// 잘못된 코드: flags & 0b0010 == 0 → flags & (0b0010 == 0) → flags & false → 컴파일 에러
// 올바른 코드: 괄호로 명확히
boolean hasBit = (flags & 0b0010) != 0;
System.out.println("hasBit = " + hasBit); // true

// 함정 예시 3: 논리 연산자와 대입
int x = 5, y = 3;
boolean result = x > 0 && y > 0; // (x > 0) && (y > 0) → true
System.out.println("result = " + result); // true

// 함정 예시 4: 문자열 + 연산자 순서
System.out.println(1 + 2 + "3"); // "33" (1+2=3, 3+"3"="33")
System.out.println("1" + 2 + 3); // "123" ("1"+2="12", "12"+3="123")
System.out.println("1" + (2 + 3)); // "15" (괄호로 먼저 더함)
}
}
비트 연산자 사용 시 반드시 괄호 사용

&, |, ^ 연산자는 ==, != 보다 우선순위가 낮습니다. 비트 연산 결과를 비교할 때는 항상 괄호로 묶어야 의도한 대로 동작합니다.

// 잘못된 예
if (flags & MASK == 0) { ... } // flags & (MASK == 0) 로 해석됨

// 올바른 예
if ((flags & MASK) == 0) { ... } // 괄호로 비트 연산을 먼저 수행

7. 실전 예제: 복잡한 수식 계산

아래 예제는 실제 시험 점수 처리와 등급 계산을 통해 다양한 연산자를 함께 사용하는 모습을 보여줍니다.

public class ScoreCalculator {
public static void main(String[] args) {
// 과목별 점수
int korean = 85;
int english = 92;
int math = 78;
int science = 88;
int history = 76;

// 총점 계산 (산술 연산자)
int total = korean + english + math + science + history;

// 평균 계산 (산술 연산자 + 형변환)
double average = (double) total / 5;

// 최고점 계산 (삼항 연산자 중첩)
int maxScore = (korean > english) ? korean : english;
maxScore = (maxScore > math) ? maxScore : math;
maxScore = (maxScore > science) ? maxScore : science;
maxScore = (maxScore > history) ? maxScore : history;

// 합격 여부 (비교 + 논리 연산자)
boolean pass = (average >= 70.0) && (math >= 60);

// 보너스 점수 (복합 대입 연산자)
double bonusAverage = average;
bonusAverage += 5.0; // 출석 보너스 5점

// 등급 판별 (복합 비교)
String grade;
if (bonusAverage >= 90) {
grade = "A";
} else if (bonusAverage >= 80) {
grade = "B";
} else if (bonusAverage >= 70) {
grade = "C";
} else {
grade = "F";
}

// 출력
System.out.println("===== 성적표 =====");
System.out.println("총점 : " + total + "점");
System.out.printf("평균 : %.2f점%n", average);
System.out.printf("보너스 : %.2f점%n", bonusAverage);
System.out.println("최고점 : " + maxScore + "점");
System.out.println("합격 여부: " + (pass ? "합격" : "불합격"));
System.out.println("등급 : " + grade);
}
}

실행 결과:

===== 성적표 =====
총점 : 419점
평균 : 83.80점
보너스 : 88.80점
최고점 : 92점
합격 여부: 합격
등급 : B

8. 핵심 정리

개념설명
연산자(Operator)연산을 수행하는 기호
피연산자(Operand)연산의 대상이 되는 값 또는 변수
우선순위(Precedence)여러 연산자가 있을 때 처리 순서 (높을수록 먼저)
결합 방향(Associativity)같은 우선순위의 연산자를 왼쪽 또는 오른쪽부터 처리
복합 대입 연산자+=, -= 등 연산과 대입을 한 번에 수행
실무 코딩 습관
  1. 우선순위가 불확실한 식에는 괄호를 적극 활용 하세요.
  2. 복잡한 산술식은 단계별로 변수에 나눠 저장 하면 디버깅이 쉬워집니다.
  3. 대입 연산자 체이닝(x = y = z = 0)은 간단한 초기화에만 사용하세요.