[면접] "당연히 11인 줄 알았는데 2라고?"

HenryHong·2026년 2월 2일
post-thumbnail

오늘 면접장에서 코드 한 장을 받았습니다. 4년 동안 자바로 밥 벌어 먹고살았기에, 생성자 정도는 눈 감고도 짠다는 자신감이 있었죠. 하지만 결과는 처참했습니다. 여러분도 아래 코드를 보고 10초 안에 결과를 맞춰보세요.

public class Test {
    public static void main(String[] args) {
        int age = 10;
        User user = new User(10, "hello");
        
        agePlus(age);
        agePlusUser(user);

        System.out.println(age);        // 출력값 A
        System.out.println(user.getAge()); // 출력값 B
    }

    private static void agePlus(int age) {
        age += 1;
    }

    private static void agePlusUser(User user) {
        user.setAge(user.getAge() + 1);
    }

    static class User {
        private int age;
        private String name;

        public User(int age, String name) {
            this.age += 1;  // <--- 문제의 그 줄
            this.name = name;
        }
        // Getter, Setter 생략
    }
}

당연히 1012라고 생각하셨나요?

축하합니다. 저와 함께 수치심을 나눌 준비가 되셨군요.

정답은 10과 2입니다.


new User(10, ...)를 보는 순간, 우리 뇌는 생성자 안의 코드를 당연히 this.age = age + 1 (전달받은 값에 1을 더함)로 필터링해서 해석해버립니다.

하지만 실제 코드를 뜯어보면 자바의 아주 기초적인 Variable Scope(변수 범위)초기화 문제가 숨어있습니다.

핵심 1: += 연산자의 정체

this.age += 1은 풀어쓰면 this.age = this.age + 1입니다.

여기서 우변의 this.age는 파라미터로 받은 age(10)가 아니라, 인스턴스 멤버 변수 this.age를 가리킵니다.

핵심 2: 멤버 변수의 기본값(Default Value)

자바에서 int 타입의 멤버 변수는 명시적으로 초기화하지 않으면 기본값 0을 가집니다.

결국 생성자 로직은 다음과 같이 실행됩니다:

  1. this.age는 0으로 초기화됨.
  2. 0 + 1을 수행하여 this.age1이 됨.
  3. 파라미터로 넘어온 10은 사용되지 않고 증발함.

그 후 agePlusUser 메서드에서 1 + 1이 수행되어 최종 결과는 2가 나옵니다.


만약 int age가 아니라 Wrapper 클래스인 Integer age였다면 결과가 달라졌을까요?

아니요, 여전히 결과는 10입니다.

Integer불변 객체(Immutable Object)이기 때문입니다. 메서드 내부에서 age += 1을 하는 순간 새로운 Integer 객체가 생성되어 로컬 변수에 할당될 뿐, 메서드 밖의 원본 객체에는 아무런 영향을 주지 못합니다.


4년 차 개발자로서 기본 중의 기본인 생성자 로직에서 털리고 나니, 쥐구멍에라도 숨고싶은 하루였습니다. 자바는 알면 알수록 깐깐하고, 내 뇌는 생각보다 믿을 게 못 된다는 걸 다시 한번 느꼈습니다.

profile
주니어 백엔드 개발자

2개의 댓글

comment-user-thumbnail
2026년 2월 2일

부끄러운걸 부끄럽게 여기지 않는 모습이 멋집니다.

답글 달기
comment-user-thumbnail
2026년 2월 10일

생성자에 age 인자 받아놓고 안쓸거면 왜 받는거야;;
문제를 위한 문제 같네요
수고하셨습니다

답글 달기