Java boolean에서 &와 &&는 같은 진리표 결과를 냅니다. 하지만 &는 양쪽 피연산자를 평가하고, &&는 왼쪽 값이 false이면 오른쪽 식을 실행하지 않습니다.

그래서 오른쪽 식에 메서드 호출이나 상태 변화가 있으면 결과값은 같아도 실행 횟수는 달라질 수 있습니다. 여기서는 숫자 비트 연산이 아니라 두 피연산자가 boolean인 경우를 다룹니다.

진리값은 같아도 오른쪽 실행 여부는 다릅니다

Java에서 boolean 값에 &를 적용하면 두 값이 모두 true일 때만 결과가 true입니다. 조건 AND 연산자인 &&도 두 값이 모두 true일 때 true를 돌려줍니다. 따라서 입력값만 놓고 표를 그리면 둘의 진리값은 같습니다. 차이는 실행 과정에 있습니다. JLS 21은 &&의 왼쪽 피연산자를 먼저 평가하고, 그 값이 false이면 오른쪽 피연산자를 평가하지 않는다고 규정합니다. 반면 boolean &는 일반 & 연산자로 양쪽 피연산자의 값을 계산합니다. 오른쪽에 메서드 호출이 들어 있으면 이 차이가 호출 횟수로 드러납니다. 결과 boolean만 적으면 부수 효과를 놓칠 수 있습니다.

오른쪽 메서드가 호출된 횟수를 세는 Java 21 교육용 예제입니다. 현재 환경에는 Java 런타임이 없어 실행 결과를 검증하지 않았습니다.
public class BooleanEvaluation {
    static int calls;

    static boolean check() {
        calls++;
        return true;
    }

    public static void main(String[] args) {
        calls = 0;
        boolean andResult = false & check();
        System.out.println(andResult + " calls=" + calls);

        calls = 0;
        boolean shortCircuitResult = false && check();
        System.out.println(shortCircuitResult + " calls=" + calls);
    }
}

false &는 호출을 세고 false &&는 건너뜁니다

첫 식은 false & check()입니다. 왼쪽 값 false만으로 최종 결과가 false라는 점은 알 수 있지만, &의 오른쪽 check()도 평가됩니다. 메서드가 호출 횟수를 1 올리고 true를 돌려주므로 결과는 false이고 호출 횟수는 1입니다. 두 번째 식은 false && check()입니다. 왼쪽 피연산자를 먼저 읽은 뒤 false를 얻습니다. 조건 AND는 이 경우 최종 결과가 false로 확정되므로 오른쪽을 평가하지 않습니다. 호출 횟수는 0입니다. 두 결과값은 모두 false이지만, 메서드 실행 횟수는 각각 1과 0입니다. 코드 추적 문제에서 함수 호출이나 변수 변경이 들어 있으면 결과와 부수 효과를 각각 적어야 하는 이유입니다.

boolean 결과와 오른쪽 메서드 실행 횟수를 분리해 기록합니다
식왼쪽 값오른쪽 호출결과calls
false & check()false실행false1
false && check()false건너뜀false0
true & check()true실행true1
true && check()true실행true1

왼쪽이 true인 마지막 두 경우에는 두 연산자 모두 오른쪽을 평가합니다. &&는 오른쪽을 항상 건너뛰는 연산자가 아닙니다. 왼쪽 값에 따라 필요할 때만 평가합니다. 오른쪽 결과가 false라면 전체 결과도 false가 됩니다. 즉 short-circuit 여부는 왼쪽이 결정 결과를 이미 확정했는지로 판단합니다.

식의 결과와 호출 수를 두 번 추적합니다

  1. 피연산자 타입이 boolean인지 확인해 정수 비트 연산과 구분합니다.
  2. 왼쪽 피연산자의 값을 먼저 적습니다.
  3. 연산자가 &이면 오른쪽도 평가하고, &&이면 왼쪽 false에서 종료합니다.
  4. 실행한 메서드의 반환값으로 전체 boolean 결과를 계산합니다.
  5. 메서드 호출, 카운터 변경, 출력처럼 관찰 가능한 부수 효과를 별도 열에 적습니다.

문제에서 if (isReady() && load())처럼 메서드 이름이 나오면 호출 순서를 먼저 표시해 보세요. isReady()가 false를 돌려주면 load()는 실행되지 않습니다. 만약 첫 연산자가 boolean &라면 load()도 호출됩니다. 양쪽 메서드가 매번 같은 결과만 돌려준다고 해도 호출 여부는 외부 상태, 로그, 시간 소모에 영향을 줄 수 있으므로 의미상 같다고 단정할 수 없습니다.

숫자 비트 AND와 boolean 조건 AND를 혼동하지 않습니다

흔한 실수는 &가 언제나 단락 평가한다고 생각하거나, 반대로 boolean &와 정수 비트 &를 같은 결과표 하나로 처리하는 것입니다. 정수 피연산자에서는 &가 각 비트에 AND를 적용합니다. boolean 피연산자에서는 논리 AND 결과를 만들지만 두 피연산자는 계산됩니다. Java에는 조건 AND인 &&가 따로 있고, 이 연산자만 왼쪽이 false일 때 오른쪽 평가를 생략합니다. 또 다른 실수는 결과가 같으므로 두 식을 서로 바꾸어도 프로그램이 같다고 보는 것입니다. 오른쪽 식에 count++, 상태 변경, 예외 발생 가능성이 있으면 실행 여부 차이가 결과 외의 관측값을 바꿉니다. 반대로 오른쪽이 부수 효과 없는 단순 boolean 값이라면 이 비교에서 호출 횟수 차이는 없을 수 있습니다. 구체적인 코드에 메서드 호출이 있는지 보고 결론을 적용하세요.

정답을 가리고 확인해 보세요

이 글을 위해 만든 학습 예시이며 공식 기출문제나 판매 카드의 인용이 아닙니다.

false & check()와 false && check()를 실행하면 각각 결과와 check 호출 횟수는 어떻게 되나요?

정답과 해설 확인두 식의 boolean 결과는 false입니다. &는 check를 호출하므로 calls가 1이고, &&는 오른쪽을 평가하지 않아 calls가 0입니다.

JLS 21 §15.22.2의 boolean &는 논리 결과를 정하고, §15.23의 &&는 왼쪽 false에서 오른쪽 평가를 생략합니다. 두 절은 같은 규격 문서 안에 있습니다.