1. 기본 연산자
1-1 항과 연산자
- 연산에 사용하는 기호를 연산자(Operator)라고 합니다.
- 연산에 사용하는 값을 항(operand)라고 합니다.
- 연산자는 항의 개수에 따라 단항 연산자, 이항 연산자, 삼항 연산자로 나눌 수 있습니다.

1-2 대입 연산자
- 대입 연산자(Assignment Operator)는 말 그대로 변수에 값을 대입하는 연산자입니다.
- 대입 연산자는 이하 연산자 중 우선 순위가 가장 낮은 연산자입니다.
- 하나의 문장에 여러 연산자가 있을 때 모든 연산을 다 끝낸 후 마지막에 연산 결과를 변수에 대입하는 것입니다.
- 대입 연산자의 형식은 아래와 같습니다.

- 오른쪽 변수 값이나 식의 연산 결과를 왼쪽 변수에 대입합니다.
- 대입 연산자는 프로그래밍에서 가장 많이 사용하는 연산자입니다.

1-3 부호 연산자
- 부호 연산자는 +, - 두 가지가 있습니다.
- 더하기, 빼기 연산에 쓰는 이항 연산자이면서 부호를 나타내는 단항 연산자로도 사용합니다.

- 변수에 - 연산자만 사용한다고 해서 값 자체가 음수로 바뀌는 것은 아닙니다.

- 위 예제에서 값 자체를 음수로 바꾸려면 = 연산자(대입 연산자)를 사용하여 값을 대입해야 합니다.
1-4 산술 연산자
- 산술 연산자는 사칙 연산에서 사용하는 연사자입니다.
- 프로그램에서 산술 연산자는 덧셈(+), 뺄셈(-), 곱셈(*), 나눗셈(/), 나머지(%) 이렇게 다섯 가지가 있습니다.

- % 연산자는 나머지를 구하는 연산자입니다.
산술 연산자의 우선 순위
- 산술 연산자의 우선순위는 일반 수학의 산술 연산과 같습니다.
- 나머지를 구하는 % 연산자의 우선순위는 나눗셈 연산의 우선순위와 동일합니다.
예제 3-1 산술 연산자를 사용하여 총점과 평균 구하기
public class OperationEx1 {
public static void main(String[] args) {
int mathScore = 90;
int engScore = 70;
// 총점 구하기
int totalScore = mathScore + engScore;
System.out.println("totalScore : " + totalScore);
// 평균 구하기
double avgScore = totalScore / 2.0;
System.out.println("avgScore : " + avgScore);
}
}

1-5 증가 · 감소 연산자
- 증가 · 감소 연산자는 단항 연산자입니다.
- 연산자 앞이나 뒤에 사용하며 값을 1만큼 늘리거나 1만큼 줄임

- 연산자를 피연산자 앞에 쓰는 경우와 뒤에 쓰는 경우 그 결과 값이 전혀 다르므로 주의해야 합니다.
예제 3-2 증가·감소 연산자를 사용하여 값 연산하기
package newstudy;
public class OperationEx2 {
public static void main(String[] args) {
// 게임에서 획득한 점수는 150점
int gameScore = 150;
// gameScore에서 1만큼 더한 값을 lastScore1에 대입
int lastScore1 = ++gameScore;
System.out.println("lastScore1 : " + lastScore1); // 151
// gameScore에서 1만큼 뺀 값을 lastScore1에 대입
int lastScore2 = --gameScore;
System.out.println("lastScore2 : " + lastScore2); // 150
}
}

1-6 관계 연산자
- 관계 연산자는 항이 두 개인 이항 연산자입니다.
- 두 개의 항 중 어느 것이 더 큰지, 작은지, 같은지 등의 여부를 검사합니다.
- 관계 연산자의 결과 값은 참(true) 또는 거짓(false)으로 반환됩니다.

- 관계 연산자는 두 값을 비교하여 결과 값을 반환하므로 비교 연산자라고도 부릅니다.
- 조건식이나 반복문을 제어하는데 자주 사용하는 연산자입니다.
1-7 논리 연산자
- 논리 연산자는 중학교 수학 시간에 배운 명제를 생각하면 됩니다.
- 두 명제가 모두 참이면 논리 곱은 참이고, 두 명제 중 하나만 참이면 논리 합은 입니다.
- 참의 부정은 거짓, 거짓의 부정은 참입니다.
- 위와 같은 논리 연산을 프로그래밍 언어로 구현한 연산자가 논리 연산자입니다.
- 논리 연산자는 주로 관계 연산자와 함께 사용합니다.
- 관계 연산자의 우선순위가 논리 연산자보다 높으므로, 관계 연산자의 결과 값을 기반으로 논리 연산자의 결과 값을 계산합니다.

- 아래는 논리 연산자의 기능을 알아보는 간단한 예입니다.

- 위 코드를 보면 논리 곱(&&) 연산에서 두 항의 결과 값이 모두 참인 경우만 참이고 그렇지 않으면 거짓이 됩니다.
- 논리 합(||) 연산은 두 항 중 하나의 항만 참인 경우에도 결과 값은 참이 됩니다.
논리 연산에서 모든 항이 실행되지 않는 경우 - 단락 회로 평가
- &&(논리 곱) 연산은 두 항이 모두 참일 때만 결과 값이 참이 됩니다.
- 즉 하나의 항이라도 거짓이면 결과 값이 거짓이 됩니다.
- ||(논리 합) 연산은 하나의 항이 참이면 나머지 항과 상관없이 결과 값은 무조건 참이 됩니다.
예제 3-3 단락 회로 평가 실습하기
public class OperationEx3 {
public static void main(String[] args) {
int num1 = 10;
int i = 2;
// 논리 곱에서 앞 항의 결과 값이 거짓이므로 뒷 문장은 실행되지 않음
boolean value = ((num1 = num1 + 10) < 10) && ((i = i + 2) < 10);
System.out.println("value : " + value);
System.out.println("num1 : " + num1);
System.out.println("i : " + i);
// 논리 합에서 앞 항의 결과 값이 참이므로 뒷 문장은 실행되지 않음
System.out.println("========================");
value = ((num1 = num1 + 10) > 10) || ((i = i + 2) < 10);
System.out.println("value : " + value);
System.out.println("num1 : " + num1);
System.out.println("i : " + i);
}
}

- 논리 곱은 앞 항의 결과 값이 거짓이면 뒤에 나오는 항과 관계없이 거짓입니다.
- 따라서 그 다음에 오는 (i = i + 2) < 10 문장은 아예 실행조차 되지 않기 때문에 i 값을 출력해보면 값이 증가하지 않았습니다.
- 논리 합은 앞 항의 결과 값이 참이면 뒤에 나오는 항과 상관없이 결과 값은 참이 됩니다.
- 따라서 (i = i + 2) < 10의 결과 값은 살펴볼 필요가 없으므로 실행조차 되지 않아 i 값은 증가하지 않습니다.
- 이와 같이 논리 곱 논리 합 연사을 할 때 두 항을 모두 실행하지 않더라도 결과 값을 알 수 있는 경우, 나머지 항은 실행되지 않는 것을 단락 회로 평가(Short Circuit Evaluation : SCE)라고 합니다.
1-8 복합 대입 연산자
- 복합 대입 연산자란 대입 연산자와 다른 연산자를 조합해 하나의 연산자처럼 사용하는 연산자입니다.
- 산술 연산자, 비트 연산자와함께 사용하여 코드를 간결하게 표현할 수 있습니다.
- 대입 연사자는 우선순위가 가장 낮은 연산자로, 연산이 모두 끝난 후 마지막으로 결과 값을 변수에 대입합니다.
- 복합 대입 연산자 역시 연산한 결과 값을 변수에 대입합니다.
- 복합 대입 연산자는 산술 연산자와 함께 자주 사용하므로 잘 이해해두면 좋습니다.

- 위 표에서 설명한 내요을 보면 알 수 있듯이 복합 대입 연산자를 사용하면 변수를 반복적으로 사용하지 않아도 되는 장점이 있습니다.
1-9 조건 연산자
- 조건 연산자는 연산에 필요한 항의 개수가 세 개입니다.
- 삼항 연산자라고 불림
- 조건 연산은 주어진 조건식이 참인 경우와 거짓인 경우에 다른 결과 값이 나옵니다.

예제 3-4 조건 연산자를 사용하여 부모님의 나이 비교하기
public class OperationEx4 {
public static void main(String[] args) {
int fatherAge = 45;
int motherAge = 47;
char ch;
ch = (fatherAge > motherAge) ? 'T' : 'F';
System.out.println("ch : " + ch);
}
}

- fatherAge와 motherAge를 비교하여 fatherAge가 motherAge보다 크면 'T', 그렇지 않으면 'F'를 변수 ch에 대입합니다.
- 위 예제에서는 fatherAge가 motherAge보다 작은 값이므로 변수 ch에는 문자 'F'가 대입됩니다.
2. 비트 연산자
- 비트 연산자는 말 그대로 비트 단위로 연산이 이루어지는 연산자입니다.
- 비트 단위의 연산을 하는 경우는 '암호화' 작업처럼 임의의 숫자를 만들거나, 어떤 변수의 특정 비트를 꺼내보는(마스킹:maskin) 경우에 사용합니다.
- 프로그램에서 특정 값을 만들거나 연산할 때 비트 연산자를 사용합니다.
2-1 비트 논리 연산자
- 비트 단위로 &, |, ^, ~ 연산이 이루어집니다.
& 연산자
- &(AND) 연산자는 두 개의 비트 값이 모두 1인 경우에만 연산의 결과 값이 1이 됩니다.
- 앞에서 본 논리 연산과 유사합니다.
| 연산자
- | (OR) 연산자는 비트 값이 하나라도 1이면 연산 결과 값이 1이 됩니다.
^ 연산자
- ^(XOR) 연산자는 같은 값이면 0, 다른 값이면 1의 결과 값을 가집니다.
~ 연산자
- ~(반전) 연산자는 비트 값을 0은 1로, 1은 0으로 바꾸는 연산자입니다.
2-2 비트 이동 연산자
- 비트 이동 연산자는 <<, >>, >>> 이렇게 세 가지가 있습니다.
- 쉬프트(shift) 연산자라고도 부릅니다.
<< 연산자
- << 연산자는 왼쪽으로 비트를 이동하는 연산자입니다.
- 왼쪽으로 n비트 이동한다는 것은 기존 값에 2ⁿ만큼 곱한다는 뜻입니다.
>> 연산자
- >> 연산자는 오른쪽으로 비트를 이동하는 연산자입니다.
- 오른쪽으로 n비트 이동하면 기존 값을 2ⁿ만큼 나눈다는 뜻입니다.
>>> 연산자
- >>> 연산자는 >> 연산과 동일하게 비트를 오른쪽으로 이동하는 연산자입니다.
- >>와 차이점은 >>> 연산자는 왼쪽에 채워지는 비트 값이 부호 비트와 상관없이 무조건 0이 됩니다.
예제 3-5 비트 이동 연산자를 사용하여 연산하기
public class OperationEx5 {
public static void main(String[] args) {
// 5를 8비트 진수로 나타냄
int num = 0B00000101;
System.out.println("num : " + (num << 2));
System.out.println("num : " + (num >> 2));
System.out.println("num : " + (num >>> 2));
// num에 값을 대입하지 않았으므로 비트 이동과 관계없이 기존 값 그대로 출력
System.out.println("num : " + (num));
// 왼쪽으로 2비트 이동한 값을 다시 num에 대입
num = num << 2;
System.out.println("num : " + (num));
// 왼쪽으로 2비트 이동한 값을 다시 num에 대입
num <<= 2;
System.out.println("num : " + (num));
}
}

- num 값을 참조해서 이동했을 뿐 이동한 값을 num에 대입하지 않았기 때문에, 비트를 이동했다고 해서 num 값이 바로 변하지는 않습니다.
2-3 연산자 우선순위
- 우선순위에 따라 컴퓨터가 연산을 수행하고 그 결과가 달라지기 때문에 우선순위를 이해해야 합니다.
일반적인 우선순위
- 1) 단항 연산자가 가장 높고 이항, 삼항 연산자 순서
- 2) 대입 연산자의 우선순위가 가장 낮음
- 3) 산술, 관계, 논리, 대입 연산자 순서로 우선순위를 가지며 ( )의 우선순위가 가장 높음