비트 연산자는 정수 타입(byte, short, int, long, char) 피연산자를 이진수(bit) 단위로 연산한다. 0과 1을 대상으로 논리 판단을 내린다고 생각하면 쉽다.
| 연산자 | 이름 | 설명 |
|---|---|---|
& |
비트 AND | 두 비트가 모두 1일 때만 1 |
\| |
비트 OR | 두 비트 중 하나라도 1이면 1 |
^ |
비트 XOR | 두 비트가 다르면 1, 같으면 0 (배타적) |
~ |
비트 NOT | 0은 1로, 1은 0으로 반전 (보수) |
10 & 12): 공통된 비트만 추출
1010 & 1100 = 1000 (십진수 8)10 | 12): 두 비트를 합침
1010 | 1100 = 1110 (십진수 14)10 ^ 12): 서로 다른 부분만 체크
1010 ^ 1100 = 0110 (십진수 6)~)의 함정~ 연산자는 부호 비트까지 반전시킨다. 따라서 양수에 ~를 붙이면 음수가 된다.
~x = -(x + 1)~10의 결과는 -11&&, ||)와의 차이점&&, ||는 boolean 타입만 연산하며, 단락 평가를 수행&, |는 정수 타입에 쓰이면 비트 연산을 하고, boolean 타입에 쓰이면 단락 평가 없는 논리 연산을 수행여러 개의 boolean 상태값을 하나의 int 변수에 담아 관리할 때 주로 사용한다. (권한 관리, 플래그 등)
int READ = 1; // 0001
int WRITE = 2; // 0010
int DELETE = 4; // 0100
int myPermission = READ | WRITE; // 0011 (읽기, 쓰기 권한 있음)
// 권한 확인 (AND 연산 활용)
if ((myPermission & READ) > 0) {
System.out.println("읽기 권한이 있습니다.");
}
보통 두 변수의 값을 바꿀 때는 temp라는 임시 변수를 쓰지만, XOR을 사용하면 변수 두 개만으로 맞바꾸기가 가능하다.
int a = 5; // 이진수: 0101
int b = 9; // 이진수: 1001
a = a ^ b; // a = 0101 ^ 1001 = 1100 (12)
b = a ^ b; // b = 1100 ^ 1001 = 0101 (5) <- b가 처음의 a값이 됨
a = a ^ b; // a = 1100 ^ 0101 = 1001 (9) <- a가 처음의 b값이 됨
System.out.println("a: " + a + ", b: " + b); // 결과 -> a: 9, b: 5
데이터에 특정 ‘키(Key)’를 넣고 XOR하면 암호화가 되고, 그 결과에 다시 같은 ‘키’를 넣고 XOR하면 원래 데이터로 복구된다.
int data = 12345; // 원본 데이터
int key = 777; // 비밀 키
// 암호화
int encrypted = data ^ key;
System.out.println("암호화된 값: " + encrypted);
// 복호화 (암호화된 값에 다시 같은 키로 XOR)
int decrypted = encrypted ^ key;
System.out.println("복호화된 값: " + decrypted); // 결과: 12345
배열 안에 모든 숫자가 두 번씩 들어있고 딱 하나만 혼자 있을 때 그 숫자를 찾으려면 모든 요소를 XOR하면 된다.(똑같은 숫자끼리 만나면 0이 되어 사라지기 때문)
int[] nums = {2, 5, 3, 2, 5};
int result = 0;
for (int n : nums) result ^= n;
System.out.println(result); // 결과: 3 (나머지는 쌍으로 사라짐)
^ (XOR)는 암호화나 두 값을 임시 변수 없이 바꿀 때 유용하다.int보다 작은 타입은 int로 변환되어 계산된다.