자바 변수 완전 정복 — 타입, 스코프, final, var 한 번에 정리

목차

  • [개념 요약]
  • [예제 코드]
  • [동작 원리]
  • [요약]

개념 요약

  • 변수(Variable): 값을 담는 이름 있는 저장소. 자바에서는 타입(Types) 으로 메모리 크기·표현 범위를 결정해.
  • 원시 타입(Primitive) vs 참조 타입(Reference): int, double, boolean 등은 값 자체를 담고, String, 배열, 객체 등은 힙(Heap) 의 객체를 가리키는 참조(reference) 를 담아.
  • 스코프(Scope)와 수명(Lifetime): 블록 {} 기준으로 접근 가능 범위가 정해지고, 지역 변수는 스택 에서 블록이 끝나면 사라져. 필드는 객체 수명과 같아.
  • 상수(constant)와 final: final재할당 금지. 원시 타입은 값 자체가 고정, 참조 타입은 참조 자체 가 고정(객체 내부 상태는 별개).
  • 타입 추론(Type inference) var(Java 10+): 로컬 변수 에 한해 컴파일러가 타입을 유추. 읽기 쉬움 이 전제될 때만 사용 추천.

왜 중요한가?
변수는 모든 로직의 최소 단위야. 타입·스코프·불변성 규칙을 명확히 알면 NullPointerException, 부정확한 캐스팅, 예상치 못한 변경 같은 버그를 크게 줄일 수 있어.

자주 쓰는 원시 타입 요약

타입 비트 기본값(필드) 예시 리터럴
byte 8 0 (byte) 1
short 16 0 (short) 7
int 32 0 42
long 64 0L 42L
float 32 0.0f 3.14f
double 64 0.0d 3.14, 2.0d
char 16 \u0000 'A', '가'
boolean 1(논리) false true, false

참고: 지역 변수의 기본값은 없다. 초기화하지 않으면 컴파일 오류.

예제 코드

1) 변수 선언·초기화·스코프·final·var 한 번에 보기

public class VariableBasics {
    // 필드(멤버 변수): 객체 수명과 동일, 기본값 존재
    private int count;          // 기본값 0
    private String name;        // 기본값 null
    private static final int MAX_SIZE = 100; // 클래스 상수(컴파일 시 상수 풀)

    public void run() {
        // 지역 변수: 반드시 초기화 필요, 블록 종료 시 소멸(스택 프레임)
        int local = 10;
        final double PI = 3.14159; // 재할당 불가

        // var: Java 10+, 지역 변수에만 사용 가능(명확할 때만)
        var title = "Hello";         // 컴파일러가 String으로 추론
        var numbers = new int[] {1, 2, 3};

        // 블록 스코프
        {
            int inner = local + 5;
            System.out.println(inner);  // 15
        }
        // System.out.println(inner);  // 컴파일 오류: inner는 블록 밖에서 접근 불가

        // 캐스팅과 리터럴
        long big = 42L;                // L 접미사
        float ratio = 0.75f;           // f 접미사
        char ch = '가';                 // 2바이트 유니코드
        boolean ok = true;

        // 참조 타입: 변수에 저장되는 건 '객체의 참조'
        String s1 = "abc";
        String s2 = s1;                // 같은 객체를 가리킴(참조 복사)
        s1 = s1.toUpperCase();         // 새 String 생성(불변)
        System.out.println(s2);        // "abc"

        // final 참조: 참조 변경만 금지, 객체 상태 변경은 별개
        final StringBuilder sb = new StringBuilder("hi");
        sb.append("!");                // OK: 내부 상태 변경
        // sb = new StringBuilder();   // 컴파일 오류: 참조 재할당 불가
    }

    public static void main(String[] args) {
        new VariableBasics().run();
    }
}

2) "자바는 값에 의한 호출" 증명: 원시 vs 참조

class Counter { int value; }

public class PassByValue {
    static void changePrimitives(int x) {
        x = 999;              // 호출자 변수에 영향 없음(값 복사)
    }

    static void changeReference(Counter c) {
        c.value = 999;        // 같은 객체를 가리키는 '참조의 복사'이므로 내부 상태는 바뀜
        c = new Counter();    // 참조 자체를 새로운 객체로 바꿔도 호출자 참조엔 영향 없음
        c.value = -1;
    }

    public static void main(String[] args) {
        int a = 1;
        changePrimitives(a);
        System.out.println(a); // 1

        Counter cnt = new Counter();
        cnt.value = 1;
        changeReference(cnt);
        System.out.println(cnt.value); // 999
    }
}

동작 원리

  • 메모리 모델: 지역 변수는 스택 프레임 에 저장되고 블록/메서드 종료 시 소멸. 객체는 에 생성되고, 참조 변수는 힙 객체의 주소 비슷한 정보를 저장해.
  • 값에 의한 호출(Call by Value): 메서드 인자는 항상 복사본 으로 전달돼. 원시 타입은 값이 복사되고, 참조 타입은 참조 값 이 복사돼서 같은 객체를 가리키게 된다.
  • final의 의미: 원시 타입은 값이 고정. 참조 타입은 참조 변경만 금지 이므로, 불변성을 원하면 String, record, 불변 컬렉션 등을 사용하거나 방어적 복사를 적용해.
  • var 사용 기준: 타입이 우변에서 명확 할 때만(예: new ArrayList<String>()). 공개 API나 복잡한 제네릭에선 명시적 타입 이 가독성을 높인다.
  • 기본값 규칙: 필드/배열 요소엔 타입별 기본값이 자동으로 채워지지만, 지역 변수는 반드시 초기화 해야 한다. 미초기화 시 컴파일 오류로 막아 버그를 예방한다.

대안과 선택 기준

  • 불변 데이터가 필요하면: final + 불변 타입(String, LocalDate, List.of(...)) 또는 Lombok의 @Value, Java 16+의 record 활용.
  • 가독성이 우선이면: var 과용 금지. 팀 컨벤션에 맞춰 "명확성 > 타이핑 단축" 원칙.
  • 성능 고려: 박싱/언박싱 자동 변환(auto boxing/unboxing) 비용 유의(intInteger). 컬렉션에 원시 타입을 직접 담을 수 없으니 필요한 최소 범위에서만 래퍼 사용.

요약

  • 변수는 타입·스코프·수명 을 정확히 이해해야 안전해. 지역 변수는 초기화 필수, 필드/배열은 기본값이 자동으로 채워진다.
  • 자바의 인자 전달은 항상 값 복사. 참조 타입은 참조의 값 을 복사하므로, 메서드에서 객체 내부 상태는 바뀔 수 있다.
  • final재할당만 금지. 진짜 불변을 원하면 불변 타입/패턴을 쓰자.
  • var로컬·명확할 때만. 공개 API나 복잡한 타입은 명시적 선언 이 읽기 좋다.
  • 이어서 보면 좋은 주제: 오토 박싱/언박싱, String/컬렉션 불변성 패턴.

'Backend > Java' 카테고리의 다른 글

[JAVA] 예외처리  (0) 2025.09.22
[JAVA] 클래스  (0) 2025.09.15
[JAVA] 반복문  (0) 2025.09.08
[Java] 기본형 vs 참조형  (1) 2025.02.11
스파르타 코딩 클럽 SQL 1주차  (0) 2022.06.28

+ Recent posts