Java 기초 - 논리 연산자, 삼항 연산자, 비트 연산자 및 핵심 면접 문제

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. 값1과 값2가 모두 상수 → 값의 범위가 큰 타입으로 반환
  2. 값1과 값2가 모두 변수 → 값의 범위가 큰 타입으로 반환
  3. 값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 연산과 동일

태그: java operator logical-operator bitwise-operator ternary-operator

6월 9일 23:00에 게시됨