1. 논리 연산자
1.1 연산자 종류
| 연산자 | 설명 |
|---|---|
| & | AND (논리곱) |
| && | 단축 AND |
| | | OR (논리합) |
| || | 단축 OR |
| ^ | XOR (배타적 논리합) |
| ! | NOT (논리 부정) |
1.2 &와 &&의 차이점
& (AND): 두 피연산자가 모두 true일 때만 true 반환
System.out.println(true & true); // true
System.out.println(false & true); // false
System.out.println(false & false); // false
&& (단축 AND): 기본 동작은 &와 동일
핵심 차이점:
&: 첫 번째 피연산자가 false여도 두 번째 피연산자까지 평가&&: 첫 번째 피연산자가 false면 두 번째 피연산자 평가 생략 (효율적)
// & 사용 - 10/0에서 ArithmeticException 발생
System.out.println(false & 10/0 > 5);
// && 사용 - 두 번째 조건 평가 안 함, 예외 없이 false 반환
System.out.println(false && 10/0 > 5);
1.3 |와 ||의 차이점
| (OR): 두 피연산자 중 하나라도 true면 true 반환
System.out.println(true | true); // true
System.out.println(false | true); // true
System.out.println(false | false); // false
System.out.println(true | false); // true
|| (단축 OR): 기본 동작은 |와 동일
핵심 차이점:
|: 첫 번째 피연산자가 true여도 두 번째 피연산자까지 평가||: 첫 번째 피연산자가 true면 두 번째 피연산자 평가 생략 (효율적)
// | 사용 - ArithmeticException 발생
System.out.println(true | 10/0 > 5);
// || 사용 - true 반환, 예외 없이 실행
System.out.println(true || 10/0 > 5);
1.4 ^ (XOR)
두 피연산자가 서로 다르면 true, 같으면 false 반환
System.out.println(true ^ true); // false
System.out.println(false ^ true); // true
System.out.println(false ^ false); // false
System.out.println(true ^ false); // true
1.5 ! (NOT)
boolean 값을 반전시킴
boolean flag1 = true;
System.out.println(!flag1); // false
boolean flag2 = false;
System.out.println(!flag2); // true
2. 삼항 연산자
2.1 표현식의 종류
- 산술 표현식:
5 + 6 - 관계 표현식:
5 > 6
2.2 문법
변수 = (조건식) ? 값1 : 값2;
동작 원리:
- 조건식이 true → 값1을 변수에 할당
- 조건식이 false → 값2를 변수에 할당
int result = (true) ? 10 : 20;
System.out.println(result); // 10
int result2 = (false) ? 10 : 20;
System.out.println(result2); // 20
2.3 응용 예제
import java.util.Scanner;
public class MaximumFinder {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("첫 번째 숫자: ");
int num1 = scanner.nextInt();
System.out.print("두 번째 숫자: ");
int num2 = scanner.nextInt();
System.out.print("세 번째 숫자: ");
int num3 = scanner.nextInt();
int max = (num1 > num2) ? num1 : num2;
max = (max > num3) ? max : num3;
System.out.println("최대값: " + max);
}
}
2.4 세 숫자 오름차순 정렬
int max = (num1 > num2) ? num1 : num2;
max = (max > num3) ? max : num3;
int min = (num1 < num2) ? num1 : num2;
min = (min < num3) ? min : num3;
int middle = num1 + num2 + num3 - max - min;
System.out.println(min + " < " + middle + " < " + max);
3. 삼항 연산자 반환 타입 규칙 (면접 중요)
3.1 반환 타입 결정 규칙
- 값1과 값2가 모두 상수 → 값의 범위가 큰 타입으로 반환
- 값1과 값2가 모두 변수 → 값의 범위가 큰 타입으로 반환
- 값1과 값2가 서로 다른 타입 (상수 + 변수)
- 상수가 변수의 타입 범위 내에 있으면 변수의 타입으로 반환
- 그렇지 않으면 상수의 타입으로 반환
3.2 예제 분석
int a = 5;
System.out.println((a < 5) ? 10.9 : 9);
// 9 반환, double 타입으로 자동 형변환됨 → 9.0
char ch = 'x'; // Unicode: 120
int num = 10;
System.out.println(false ? num : ch);
// 'x'의 Unicode 값 120이 int로 변환되어 반환
char ch = 'x';
int smallNum = 100;
int largeNum = 1000000;
System.out.println(false ? smallNum : ch); // 'x' (120)
System.out.println(false ? largeNum : ch); // 120 (int로 변환)
참고: 상수는 컴파일 타임에 값이確定되어 타입 범위 확인이 가능함
4. 비트 연산자
4.1 이해
십진수를 이진수로 변환한 후 각 자리의 비트 단위로 연산 수행
4.2 이진수 변환 이해
// 23의 이진수: 0001 0111
// 2^0 + 2^1 + 2^2 + 2^4 = 1 + 2 + 4 + 16 = 23
// -23의 이진수 (2의 보수)
// 23: 0001 0111
// 1의 보수: 1110 1000
// 2의 보수: 1110 1001 (가장 낮은 비트에 1 추가)
4.3 연산자 종류
| 연산자 | 설명 |
|---|---|
| & | 비트 AND |
| | | 비트 OR |
| << | 왼쪽 시프트 |
| >> | 오른쪽 시프트 (부호 비트 유지) |
| >>> | 오른쪽 시프트 (부호 비트 무시, 0으로 채움) |
4.4 & (비트 AND)
같은 위치의 비트가 모두 1일 때만 결과가 1
byte val1 = 23; // 0001 0111
byte val2 = 27; // 0001 1011
byte result = (byte)(val1 & val2);
System.out.println(result); // 19 → 0001 0011
// 상세 분석:
// val1 (byte): 0001 0111
// val1 (int): 0000 0000 0000 0000 0000 0000 0001 0111
// val2 (byte): 0001 1011
// val2 (int): 0000 0000 0000 0000 0000 0000 0001 1011
// 결과: 0000 0000 0000 0000 0000 0000 0001 0011
// byte 변환: 0001 0011 → 19
4.5 | (비트 OR)
같은 위치의 비트 중 하나라도 1이면 결과가 1
4.6 ^ (비트 XOR)
같은 위치의 비트가 다르면 1, 같으면 0
4.7 << (왼쪽 시프트)
전체 비트를 왼쪽으로 n만큼 이동, 오른쪽 빈자리는 0으로 채움
int value = 128;
System.out.println(value << 2); // 512
// 128: 0000 0000 0000 0000 0000 0000 1000 0000
// 512: 0000 0000 0000 0000 0000 0010 0000 0000
// 중요: 왼쪽 시프트 1회당 2배 증가
// 128 << 1 = 256
// 128 << 2 = 512
4.8 >> (오른쪽 시프트)
전체 비트를 오른쪽으로 n만큼 이동, 왼쪽 빈자리는 부호 비트로 채움
int negative = -128;
System.out.println(negative >> 2);
// -128의 이진수: 1111 1111 1111 1111 1111 1111 1000 0000
// 2회 시프트: 1111 1111 1111 1111 1111 1111 1110 0000
4.9 >>> (부호 없는 오른쪽 시프트)
전체 비트를 오른쪽으로 n만큼 이동, 왼쪽 빈자리는 항상 0으로 채움
int negative = -128;
System.out.println(negative >>> 2);
// -128: 1111 1111 1111 1111 1111 1111 1000 0000
// 결과: 0011 1111 1111 1111 1111 1111 1110 0000 (양수)
5. 정리
& | ^가 boolean 피연산자 사용 → 논리 연산자& | ^가数值 피연산자 사용 → 비트 연산자<<1회 이동는 2배 연산과 동일>>1회 이동는 1/2 연산과 동일