연산자는 연산에 사용되는 표시나 기호를 말합니다.
| 구분 | 설명 |
|---|---|
| 연산자(operator) | 연산을 수행하는 기호(+, - , *, /...) |
| 피연산자(operland) | 연산되는 데이터.(변수, 상수, 리터럴, 수식) |
💡 [피연산자] + [피연산자] - [피연산자]
위의 식처럼 1 + 2 + 3을 작성하면 계산만 되고 계산된 결과는 사라집니다. 우리는 결과값을 재사용하거나 추후 출력하기 위해서는 어딘가에 저장을 해둬야합니다. 바로 이전 게시글에서 공부했던 변수에 담아야합니다. 이때 대입 연산자 =를 사용하는데 변수에 대입할 때는 대입할 값은 무조건 변수의 오른쪽에 위치해야 합니다.
int sum = 1 + 2 + 3;
System.out.println(sum); // 6
System.out.println(1 + 2 + 3); // 6 -> 이렇게 해도 6이 출력은 되지만 이 값은 재사용할 수 없다.
자바에서 제공하는 연산자의 종류는 아래의 표와 같습니다.
| 종류 | 설명 |
|---|---|
| 증감 연산자 | ++, -- |
| 산술 연산자 | + , - , * , / , % |
| 비트 연산자 | &, |, ^, ~, <<, >>, >>> |
| 비교 연산자 | ==, !=, >=, <=, ==, !=, <, > |
| 논리 연산자 | &&, ||, ! |
| 대입 연산자 | =, +=, -=, *=, /=, %= |
| 기타 | 삼항 연산자, instanceof연산자 |
증감 연산자는 피연산자를 1씩 즈악 혹은 감소 시킬 때 사용하는 연산자 입니다. 증감연산자의 피연산자는 한 개이며 증감연산자가 피연산자의 앞에 위치하느냐 뒤에 위치하느냐에 따라 결과값이 달라집나다.
| 증감 연산자 | 설명 |
|---|---|
| ++x | 먼저 피연산자의 값을 1 증가시킨 후에 연산 진행 |
| x++ | 먼저 해당 연산을 수행하고 나서, 피연산자의 값을 1 증가 |
| --x | 먼저 피연산자의 값을 1 감소시킨 후에 연산 진행 |
| x-- | 먼저 해당 연산을 수행하고 나서, 피연산자의 값을 1 감소 |
int num1 = 5;
int num2 = 5;
int result1 = --num1 + 5; // 9
int result2 = num2-- + 5; // 10
똑같은 5에 5를 더 했는데 결과값이 달라졌습니다. 그 이유는 무엇일까요?
💡
result1에서는 증감 연산자가 피연산자의 앞에 위치해있다. 그래서 연산을 수행하기 전 피연산자의 값이 1 감소하기 때문에 4 + 5로 결과값이 9가 출력된다.
💡
result2에서는 증감 연산자가 피연산자의 뒤에 있다. 그래서 해당 연산을 수행하고나서 피연산자의 값이 1 감소하기 때문에 5 + 5로 결과값이 10이 출력된다. 결과값 10을 result에 대입하는 연산까지 수행 후 num2는 1 감소하여 4가 된다.
위의 예제처럼 증감 연산자의 위치에 따라 결과값이 완전히 달라지기 때문에 복잡한 연산이라면 오차는 더욱 커질 것입니다. 이 점에 유의하여 사용해야 합니다.
산술 연산자는 우리가 평소에 자주 사용하는 사칙연산을 다루는 연산자들이 포함되어 있습니다.
| 산술 연산자 | 설명 |
|---|---|
| + | 왼쪽의 피연산자에 오른쪽 피연산자를 더함 |
| - | 왼쪽의 피연산자에서 오른쪽의 피연산자를 뺌 |
| * | 왼쪽의 피연산자에 오른쪽의 피연산자를 곱함 |
| / | 왼쪽의 피연산자를 오른쪽의 피연산자로 나눔 |
| % | 왼쪽의 피연산자를 오른쪽의 피연산자를 나눈 값의 나머지 반환 |
int num1 = 13;
int num2 = 3;
System.out.println("+ 연산자 연산 수행 결과 : " + (num1 + num2)); // 16
System.out.println("- 연산자 연산 수행 결과 : " + (num1 - num2)); // 10
System.out.println("* 연산자 연산 수행 결과 : " + (num1 * num2)); // 39
System.out.println("/ 연산자 연산 수행 결과 : " + (num1 / num2)); // 4
System.out.println("% 연산자 연산 수행 결과 : " + (num1 % num2)); // 1
평소에 자주 사용하는 사칙연산이지만 /를 눈여겨 봐야합니다. 우리가 평소에 알던 나눗셈의 결과값으로는 4.33333333333이 나와야하는데 그냥 숫자4가 나왔습니다.
이것은 나누기의 두 연산자의 자료형이 정수형인 int이기 때문입니다. 정수형이기 때문에 소수점 아래의 자리는 저장하지 못하므로 정수만 출력되는 것입니다. 나눗셈 결과로 소수점을 버릴 때 반올림은 하지 않습니다.
그렇다면 정확한 값을 얻기 위해서는 어떻게 해야할까요?
바로 이전에 공부한 형변환을 사용해야 합니다.
int num1 = 13;
int num2 = 3;
System.out.println("result : " + (double)(num1 / num2)); // 4.0
System.out.println("result : " + ((double)num1 / num2)); // 4.33333333333
그렇다면 위의 두개의 연산결과 값은 왜 다를까요?
💡 형변환 연산 수행결과가 다른 이유
비트 연산자는 10진수의 연산보다는 2진수의 연산에 주로 사용하거나 1의 보수를 만들 때 사용합니다.
| 비트 연산자 | 설명 |
|---|---|
| | | 피연산자의 값 중 하나라도 1이면 1을 반환 (OR연산자) |
| & | 피연산자 양쪽의 값이 모두 1이어야만 1을 반환 (AND연산자) |
| ^ | 피연산자의 값이 서로 다를 때만 1을 반환 (XOR연산자) |
| ~ | 피연산자의 값이 1이면 0으로, 0이면 1로 반환 (NOT연산자, 1의 보수) |
| << | 피연산자의 bit값을 왼쪽으로 이동 (left shift 연산자) |
| >> | 피연산자의 bit값을 오른쪽으로 이동(right shift 연산자) |
| >>> | 피연산자의 bit값을 오른쪽으로 이동. 이때 새로운 비트는 전부 0으로 반환 |
다음 예제는 1byte크기를 기준으로 8bit로 연산하는 예제입니다.
int num1 = 8;
int num2 = -8;
System.out.println("~ 연산자에 의한 결과: " + ~num1); // -9
System.out.println("<< 연산자에 의한 결과: " + (num1 << 2)); // 32
System.out.println(">> 연산자에 의한 결과: " + (num2 >> 2)); // -2
System.out.println(">>> 연산자에 의한 결과: " + (num1 >>> 2)); // 2
System.out.println(">>> 연산자에 의한 결과: " + (num2 >>> 2)); // 1073741822
💡시프트(shift) 연산자
비교 연산자는 두 피연산자를 비교하는 데 사용되는 연산자 입니다. 주로 조건문과 반복문의 조건식에 사용되며, 연산결과는 논리형인 boolean형(true, false)으로 출력됩니다.
| 비교 연산자 | 설명 |
|---|---|
| > | 왼쪽의 피연산자가 오른쪽의 피연산자보다 크면 참(true)을 반환 |
| < | 왼쪽의 피연산자가 오른쪽의 피연산자보다 작으면 참(true)을 반환 |
| >= | 왼쪽의 피연산자가 오른쪽의 피연산자보다 크거나 같으면 참(true)을 반환 |
| <= | 왼쪽의 피연산자가 오른쪽의 피연산자보다 작거나 같으면 참(true)을 반환 |
| == | 양쪽의 피연산자가 같으면 참(true)을 반환 |
| != | 양쪽의 피연산자가 같이 잖으면 참(true)을 반환 |
int num1 = 3;
int num2 = 7;
System.out.println("3 > 7 = " + (num1 > num2)); // false
System.out.println("3 < 7 = " + (num1 < num2)); // true
System.out.println("3 >= 7 = " + (num1 >= num2)); // false
System.out.println("3 + 4 <= 7 = " + (num1 + 4 <= num2)); // true
System.out.println("3 == 7 = " + (num1 == num2)); // false
System.out.println("3 != 7 = " + (num1 != num2)); // true
논리 연산자는 주어진 논리식을 판단하여, 참(true)과 거짓(false)을 결정하여 boolean형의 결과값을 가지는 연산자입니다.
| 논리 연산자 | 설명 |
|---|---|
| && | 논리식이 모두 참이면 참을 반환. (AND 결합) |
| || | 논리식 중에서 하나라도 참이면 참을 반환. (OR 연산) |
| ! | 논리식의 결과가 참이면 거짓, 거짓이면 참을 반환 |
boolean w = false;
boolean x = true;
boolean y = false;
boolean z = true;
System.out.println("false && true: " + (w && x)); // false
System.out.println("true && true: " + (x && z)); // true
System.out.println("false && false: " + (w && y)); // false
System.out.println("false || true: " + (w || x)); // true
System.out.println("true || true: " + (x || z)); // true
System.out.println("false || false: " + (w || y)); // false
System.out.println("!false: " + !y); // true
System.out.println("!true: " + !x); // false
대입 연산자는 변수에 값을 대입할 때 사용하는 연산자 입니다. 자바에서는 대입 연산자와 다른 연산자를 결합한 복합 대입 연산자가 제공합니다.
| 대입 연산자 | 설명 |
|---|---|
| = | 왼쪽의 피연산자에 오른쪽의 피연산자를 대입. |
| += | 왼쪽의 피연산자에 오른쪽의 피연산자를 더한 후, 결과값을 왼쪽의 피연산자에 대입. |
| -= | 왼쪽의 피연산자에 오른쪽의 피연산자를 뺀 후, 결과값을 왼쪽의 피연산자에 대입. |
| *= | 왼쪽의 피연산자에 오른쪽의 피연산자를 곱한 후, 결과값을 왼쪽의 피연산자에 대입. |
| /= | 왼쪽의 피연산자를 오른쪽의 피연산자로 나눈 후, 결과값을 왼쪽의 피연산자에 대입. |
| %= | 왼쪽의 피연산자를 오른쪽의 피연산자로 나눈 후, 나머지값을 왼쪽의 피연산자에 대입. |
| &= | 왼쪽의 피연산자를 오른쪽의 피연산자와 비트AND 연산 후, 결과값을 왼쪽의 피연산자에 대입. |
| != | 왼쪽의 피연산자를 오른쪽의 피연산자와 비트OR 연산 후, 결과값을 왼쪽의 피연산자에 대입. |
| ^= | 왼쪽의 피연산자를 오른쪽의 피연산자와 비트XOR 연산한 후, 결과값을 왼쪽의 피연산자에 대입. |
int i = 3;
i += 3; // 6
i -= 2; // 4
i *= 3; // 12
i /= 4; // 3
i %= 2; // 1
기타 연산자로는 대표적으로 삼항 연산자와 instanceof 연산자가 있습니다.
| 기타 연산자 | 설명 |
|---|---|
| 삼항 연산자 | 물음표'?' 앞의 조건식에 따라 결과값이 참이면 반환값1을 반환하고 거짓이면 반환값2를 반환 |
| instanceof 연산자 | 참조 변수가 참조하고 있는 인스턴스의 실제 타입을 반환 |
// 삼항 연산자 예제
boolean x = true;
boolean y = false;
System.out.println(x && y ? "반환값1" : "반환값2");
// instanceof 연산자 예제
A a = new A();
B b = new B();
System.out.println(a instanceof A); // true
System.out.println(b instanceof A); // false
System.out.println(a instanceof B); // false
System.out.println(b instanceof B); // true
인스턴스에 대해서는 추후에 객체에 대해 설명을 할 때 자세히 설명하도록 하겠습니다.