연산: 프로그램에서 데이터를 처리하여 결과를 산출하는 것
연산자: 연산에 사용되는 표시나 기호
피연산자: 연산되는 데이터
연산식: 연산의 과정을 기술한 것
| 연산자 종류 | 연산자 | 피연산자 수 | 산출값 | 기능 설명 |
|---|---|---|---|---|
| 산술 | +, -, *, /, % | 이항 | 숫자 | 사칙연산 및 나머지 계산 |
| 부호 | +, - | 단항 | 숫자 | 음수와 양수의 부호 |
| 문자열 | + | 이항 | 문자열 | 두 문자열을 연결 |
| 대입 | =, +=, -=, *=, /=, %=, &=, ^=, |=, <<=, >>=, >>>= | 이항 | 다양 | 우변의 값을 좌변의 변수에 대입 |
| 증감 | ++, -- | 단항 | 숫자 | 1만큼 증가/감소 |
| 비교 | ==, !=, >, <, >=, <=, instanceof | 이항 | boolean | 값의 비교 |
| 논리 | !, &, |, &&, || | 단항 이항 | boolean | 논리적 NOT, AND, OR 연산 |
| 조건 | (조건식) ? A : B | 삼항 | 다양 | 조건식에 따라 A 또는 B 중 하나를 선택 |
| 비트 | ~, &, |, ^ | 단항 이항 | 숫자 boolean | 비트 NOT, AND, OR, XOR 연산 |
| 쉬프트 | >>, <<, >>> | 이항 | 숫자 | 비트를 좌측/우측으로 밀어서 이동 |
연산자는 피연산자의 수에 따라 단항, 이항, 삼항 연산자로 구분됩니다.
x++; // 단항 연산자
x + y; // 이항 연산자
(sum>90) ? "A" : "B"; // 삼항 연산자
연산식을 피연산자로 사용할 수 있습니다.
boolean result = (x+y) < 5;
x > 0 && y < 0
위의 연산식에서 &&보다 >,< 연산자의 우선순위가 높기 때문에 x>0과 y<0이 먼저 처리되고, &&는 먼저 연산된 산출값들을 가지고 연산을 하게 됩니다. 만약 우선순위가 같은 연산자들이 있다면 보통 왼쪽에서 오른쪽으로 연산을 진행합니다.
하지만 단항 연산자, 부호 연산자, 대입 연산자는 오른쪽에서 왼쪽으로 연산을 진행합니다. 이렇게 연산의 방향과 우선순위가 졍해져 있기 때문에 복잡한 연산식에서는 주의해야 합니다.
헷갈릴 때는 괄호(최우선순위로 연산)를 사용해서 먼저 처리해야 할 연산식을 묶어주는 것이 좋습니다.
100 * 2 / 3 % 5 // 왼쪽에서 오른쪽으로 연산
a = b = c = 5 // 오른쪽에서 왼쪽으로 연산
| 연산자 | 연산 방향 | 우선순위 |
|---|---|---|
| 증감, 부호, 비트(~), 논리(!) | <- | 높음 |
| 산술(*, /, %) | -> | | |
| 산술(+, -) | -> | | |
| 쉬프트 | -> | | |
| 비교(<, >, <=, >=, instanceof) | -> | | |
| 비교(==,!=) | -> | | |
| 논리(&) | -> | | |
| 논리(^) | -> | | |
| 논리(|) | -> | | |
| 논리(&&) | -> | | |
| 논리(||) | -> | | |
| 조건(?:) | -> | | |
| 대입 | <- | 낮음 |
| 연산자 | 설명 |
|---|---|
| + | 피연산자의 부호 유지 |
| - | 피연산자의 부호 변경 |
+, - 는 산술 연산자이기도 하고, 부호 연산자이기도 합니다.
부호 연산자로 쓰일 때에는 하나의 피연산자만 필요합니다.
일반적으로 부호 연산자는 다음과 같이 정수 및 실수 리터럴 앞에 붙여 양수 및 음수를 표현할 때 쓰입니다.
int i1 = +100;
int i2 = -100;
double d1 = +3.14;
double d2 = -10.5;
부호 연산자를 정수 또는 실수 타입 변수 앞에 붙여서 사용할 수도 있습니다.
이 경우에는 변수 값의 부호를 유지하거나 바꾸기 위해 사용됩니다. + 연산자는 변수 값의 부호를 유지하고, - 연산자는 변수 값의 부호를 양수는 음수로, 음수는 양수로 변경합니다.
int i = -100;
int result1 = +i; // -100
int result2 = -i; // 100
부호 연산자를 사용할 때는 산출 타입이 int로 변하기 때문에 주의해야 합니다. 예를 들어
short 타입 값을 부호 연산하면 int 타입 값으로 바뀝니다. 그래서 다음 코드는 컴파일 에러가 발생합니다.
short s = 100;
short result = -s; // 컴파일 에러
short s = 100;
int result = -s; // -100
| 연산식 | 설명 | |
|---|---|---|
| ++ | 피연산자 | 다른 연산을 수행하기 전에 피연산자의 값을 1 증가시킴 |
| -- | 피연산자 | 다른 연산을 수행하기 전에 피연산자의 값을 1 감소시킴 |
| 피연산자 | ++ | 다른 연산을 수행한 후에 피연산자의 값을 1 증가시킴 |
| 피연산자 | -- | 다른 연산을 수행한 후에 피연산자의 값을 1 감소시킴 |
연산식에서 증감 연산자만 있는 경우에는 증감 연산자가 변수 앞 또는 뒤 어디든 위치해도 상관없지만, 다른 연산자와 함께 사용하는 연산식에서는 증감 연산자의 위치에 따라 연산식의 결과가 달라지므로 주의해야 합니다.
int x = 1;
int y = 1;
int result1 = ++x + 10; // 12
int result2 = y++ + 10; // 11
System.out.println(y); // 2
| 연산식 | 설명 | |
|---|---|---|
| ! | 피연산자 | 피연산자가 true이면 false 값을 산출 피연산자가 false이면 true 값을 산출 |
| 연산식 | 설명 | |
|---|---|---|
| ~ | 10 (00...01010) | 산출 결과: -11 (11...10101) |
byte b1 = 10;
byte b2 = ~b1; // 컴파일 에러
byte b1 = 10;
int b2 = ~b1; // -11
| 연산식 | 설명 | ||
|---|---|---|---|
| 피연산자 | + | 피연산자 | 덧셈 연산 |
| 피연산자 | - | 피연산자 | 뺄셈 연산 |
| 피연산자 | * | 피연산자 | 곱셈 연산 |
| 피연산자 | / | 피연산자 | 좌측 피연산자를 우측 피연산자로 나눗셈 연산 |
| 피연산자 | % | 피연산자 | 좌측 피연산자를 우측 피연산자로 나눈 나머지를 구하는 연산 |
산술 연산자의 특징은 피연산자들의 타입이 동일하지 않을 경우 다음과 같은 규칙을 사용해서 피연산자들의 타입을 일치시킨 후 연산을 수행한다는 것입니다.
1. 피연산자들이 모두 정수 타입이고, int 타입보다 크기가 작은 타입일 경우 모두 int 타입으로 변환
2. 피연산자들이 모두 정수 타입이고, long 타입이 있을 경우 모두 long 타입으로 변환
3. 피연산자 중 실수 타입이 있을 경우, 크기가 큰 실수 타입으로 변환
int x = 10;
int y = 4;
int result1 = x / y;
double result2 = x / y;
// 연산 값으로 2.5를 얻으려면
double result3 = (x * 1.0) / y;
double result4 = (double) x / y;
double result5 = x / (double) y;
char 타입도 정수 타입이므로 산술 연산이 가능합니다.
char c1 = 'A' + 1; // B
char c2 = c1 + 1; // 컴파일 에러
int c2 = c1 + 1; // 67
char c2 = (char) (c1 + 1); // C
문자열 연결 연산자인 +는 문자열을 서로 결합하는 연산자입니다.
+ 연산자는 산술 연산자, 부호 연산자인 동시에 문자열 연결 연산자이기도 합니다.
피연산자 중 한쪽이 문자열이면 다른 피연산자를 문자열로 변환합니다.
"JDK" + 3 + 3.0; // "JDK33.0"
3 + 3.0 + "JDK"; // "6.0JDK"
| 구분 | 연산식 | 설명 | ||
|---|---|---|---|---|
| 동등 비교 | 피연산자1 | == | 피연산자2 | 두 피연산자의 값이 같은지를 검사 |
| 피연산자1 | != | 피연산자2 | 두 피연산자의 값이 다른지를 검사 | |
| 크기 비교 | 피연산자1 | > | 피연산자2 | 피연산자1이 큰지를 검사 |
| 피연산자1 | >= | 피연산자2 | 피연산자1이 크거나 같은지를 검사 | |
| 피연산자1 | < | 피연산자2 | 피연산자1이 작은지를 검사 | |
| 피연산자1 | <= | 피연산자2 | 피연산자1이 작거나 같은지를 검사 |
비교 연산자는 흐름 제어문인 조건문이나 반복문에서 주로 이용됩니다.
만약 피연산자가 char 타입이면 유니코드 값으로 비교 연산을 수행합니다.
또한 비교 연산자에서도 타입 변환을 통해 피연산자의 타입을 일치시킨 후 연산을 수행합니다.
'A' == 65 // true: 'A'가 int 타입(65)으로 변환됨
3 == 3.0 // true: 3이 double 타입(3.0)으로 변환됨
다음은 한 가지 예외 상황입니다. 정상적이라면 0.1f가 좌측 피연산자의 타입인
double로 변환되어 0.1 == 0.1이 되고 true가 산출되어야 하지만, 결과는 false입니다.
이유는 부동 소수점 방식으로 인해 0.1f는 0.1의 근사값으로 표현되기 때문입니다.
0.1 == 0.1f // false
String 타입의 문자열을 비교할 때에는 동등 비교 연산자를 사용할 수 있지만,
== 연산자는 변수에 저장된 값만 비교하기 때문에 객체의 값이 같아도 참조하는 주소가 다르다면 원하지 않는 결과가 나올 수도 있습니다.
String str1 = "자바 스터디";
String str2 = "자바 스터디";
String str3 = new String("자바 스터디");
System.out.println(str1 == str2); // true
System.out.println(str2 == str3); // false
그래서 동일한 객체이건 다른 객체이건 상관없이 객체의 문자열만을 비교하고 싶다면 == 연산자 대신에 equals() 메서드를 사용해야 합니다. equals() 메서드는 원본 문자열과 매개값으로 주어진 비교 문자열이 동일한지 비교한 후 값을 리턴합니다.
String str1 = "자바 스터디";
String str2 = new String("자바 스터디");
System.out.println(str1.equals(str2)); // true
| 구분 | 연산식 | 결과 | 설명 | ||
|---|---|---|---|---|---|
| AND (논리곱) | true | && 또는 & | true | true | 피연산자 모두가 true일 경우에만 연산 결과 true |
| true | false | false | |||
| false | true | false | |||
| false | false | false | |||
| OR (논리합) | true | || 또는 | | true | true | 피연산자 중 하나만 true이면 연산 결과 true |
| true | false | true | |||
| false | true | true | |||
| false | false | false | |||
| XOR (배타적논리합) | true | ^ | true | false | 피연산자가 하나는 true이고 다른 하나가 false일 경우에만 연산 결과 true |
| true | false | true | |||
| false | true | true | |||
| false | false | false | |||
| NOT (논리부정) | ! | true | false | 피연산자의 논리값을 바꿈 | |
| false | true |
논리 연산자는 논리곱(&&), 논리합(||), 배타적 논리합(^) 그리고 논리 부정(!) 연산을 수행합니다.
&&와 &는 산출 결과는 같지만 연산 과정이 다릅니다. &&는 앞의 피연산자가 false라면 뒤의 피연산자를 평가하지 않고 바로 false라는 결과를 산출합니다. &는 두 피연산자 모두를 평가해서 산출 결과를 냅니다. 따라서 &보다 &&가 더 효율적으로 동작합니다.
||와 |도 마찬가지입니다.
비트 연산자는 데이터를 bit 단위로 연산합니다. 즉 0과 1이 피연산자가 됩니다. 그렇기 때문에 0과 1로 표현이 가능한 정수 타입만 비트 연산이 가능합니다. 실수 타입은 비트 연산을 할 수 없습니다.
비트 연산자는 기능에 따라 비트 논리 연산자(&, |, ^, ~)와 비트 이동 연산자(<<, >>, >>>)로 구분합니다. 일반 논리 연산자가 true와 false를 연산한다면 비트 논리 연산자는 0과 1을 연산합니다.
비트 이동 연산자는 비트를 좌측 또는 우측으로 이동시키는 연산자입니다.
비트 논리 연산자에는 &, |, ^, ~가 있습니다. &, |, ^ 연산자는 피연산자가 boolean 타입일 경우에는 일반 논리 연산자이고, 피연산자가 정수 타입일 경우에는 비트 논리 연산자로 동작합니다.

비트 이동(shift) 연산자는 정수 데이터의 비트를 좌측 또는 우측으로 밀어서 이동시키는 연산을 수행합니다.

대입 연산자는 우측 피연산자의 값을 좌측 피연산자인 변수에 저장합니다. 우측 피연산자에는 리터럴 및 변수, 연산식이 올 수 있습니다. 단순히 오른쪽 피연산자의 값을 변수에 저장하는 단순 대입 연산자와 정해진 연산을 수행한 후 결과를 변수에 저장하는 복합 대입 연산자가 있습니다.

삼항 연산자는 3개의 피연산자를 필요로 하는 연산자입니다. 물음표 앞의 조건식에 따라
콜론 앞뒤의 피연산자가 선택된다고 해서 조건 연산식이라고 부르기도 합니다.
삼항 연산자를 사용하는 방법은 다음과 같습니다.
int score = 85;
char grade = (score > 90) ? 'A' : ((score > 80) ? 'B' : 'C');
System.out.println(score + "점은 " + grade + "등급입니다.");
// 85점은 B등급입니다.
(피연산자1) ? (피연산자2) : (피연산자3)
조건식이 true라면 삼항 연산자의 결과는 피연산자2가 되고,
조건식이 false라면 결과는 피연산자3이 됩니다.