John's Code Journey

[JAVA] final - 변하지 않는 값 본문

IT공부/JAVA

[JAVA] final - 변하지 않는 값

Johnnnn 2025. 4. 23. 12:56
728x90

🔒 자바의 final 키워드란?

final은 "변경 금지" 라는 의미.
자바에서 final은 값이나 구조를 더 이상 바꿀 수 없게 만들 때 사용됨.

📌 final이 사용되는 3가지 주요 장소

대상 의미 예시
변수 한 번만 값 할당 가능 (상수처럼 사용) final int x = 10;
메서드 오버라이딩 금지 final void print() {...}
클래스 상속 금지 final class Dog {}

✅ 1. final 변수 (상수)

public class Example {
    final int x = 100; // 초기화 후 변경 불가

    public void test() {
        // x = 200; // ❌ 오류: final 변수는 수정 불가
    }
}
public class Config {
    public static final double PI = 3.14159;
    //상수를 만들 때는 보통 대문자로 이름을 써서 구분함
    //관례임
}

✅ 2. final 메서드 (오버라이딩 금지)

class Animal {
    public final void sleep() {
        System.out.println("동물이 잠을 잡니다.");
    }
}

class Dog extends Animal {
    // public void sleep() { } // ❌ 오류! 오버라이딩 불가
}
//부모 클래스에서 중요한 로직은 자식이 못 바꾸게 할 때 사용

✅ 3. final 클래스 (상속 금지)

final class Car {
    public void drive() {
        System.out.println("달립니다.");
    }
}

// class SuperCar extends Car {} // ❌ 오류! final 클래스는 상속 불가

🔥 심화: final + 객체?

final Student s = new Student("지은", 90);
s = new Student("민수", 85); // ❌ 에러!
s.name = "영희"; // ✅ 이건 가능
// ✅ 참조는 못 바꾸지만, 객체 내부의 값은 바꿀 수 있음!

 

📌 1. final과 상수

🧠 final 변수 = 상수

final 키워드는 변수에 사용될 때 상수처럼 동작하게 함
즉, 한 번 값이 할당되면 그 값을 변경할 수 없게 만드는 거임

public class Constants {
    public static final double PI = 3.14159;  // 원주율
    public static final int MAX_SIZE = 100;   // 최대 크기
}
//🔑 상수: 값이 한 번 할당되면 변경이 불가능함
//자바에서는 상수 이름을 대문자로 쓰는 것이 일반적임 (PI, MAX_SIZE처럼)

상수와 final의 차이점

  • 상수는 값이 고정된 변수라는 개념이고,
    final 변수는 "값을 한 번만 할당할 수 있다"는 의미
  • 즉, final을 사용해서 상수를 만들 수 있고, 이는 보통 public static으로 선언해 전체에서 쉽게 사용할 수 있도록 함

📌 2. 불변 객체 (Immutable Object)

🧠 불변 객체란?

불변 객체는 객체의 상태가 한 번 생성되면 절대로 변경되지 않는 객체를 말함
즉, 객체의 필드 값이 수정되지 않도록 설계된 클래스 !

❗ 왜 불변 객체가 중요한가?

  • 스레드 안전(Thread-safe): 여러 스레드에서 동시에 접근해도 문제가 생기지 않음.
  • 예측 가능한 동작: 객체 상태가 바뀌지 않아서 코드가 예측 가능하고 안전함.

📝 불변 객체 만드는 방법

  1. 클래스를 final로 선언 → 상속을 막아야 함
  2. 모든 필드를 final로 선언 → 필드 값을 변경하지 못하도록
  3. 객체의 상태를 변경하는 메서드를 제공하지 않음
  4. 객체가 생성될 때 모든 값을 초기화 → 생성 후에는 상태 변경이 불가능하게

예시: 불변 객체 만들기

final class Person {
    private final String name;
    private final int age;

    // 생성자에서 모든 필드를 초기화
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // getter만 제공 (setter는 제공하지 않음)
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

이렇게 하면 Person 객체는 한 번 생성되면 nameage를 변경할 수 없게 됨

📌불변 객체의 특징

  • 객체가 생성되면 그 이후에는 변경할 수 없다.
  • 객체의 상태가 항상 일정하게 유지된다.
  • 안전하게 공유될 수 있다: 여러 스레드에서 동시에 사용해도 데이터 일관성이 유지됨.

📌 3. final, 상수, 불변 객체의 관계

이 세 가지 개념은 데이터 변경을 방지하는 방법이라는 공통점을 가지고 있어.

  • final 변수: 값을 한 번 할당한 후 변경할 수 없는 변수 → 상수 역할을 함.
  • 상수: 변하지 않는 값을 가진 변수. 자주 public static final로 선언.
  • 불변 객체: 객체 자체의 상태가 변경되지 않는 객체. 객체의 내부 상태를 변경할 수 없도록 설계함.

예시: 상수, final과 불변 객체가 결합된 상황

final class Vehicle {
    private final String model;
    private final int year;

    // 생성자에서 초기화
    public Vehicle(String model, int year) {
        this.model = model;
        this.year = year;
    }

    public String getModel() {
        return model;
    }

    public int getYear() {
        return year;
    }

    // 불변 객체: 외부에서 상태를 변경할 수 없도록 설계
}

public class Main {
    public static final double PI = 3.14159; // 상수
    public static final Vehicle car = new Vehicle("Tesla", 2023); // 불변 객체 상수

    public static void main(String[] args) {
        System.out.println("차량 모델: " + car.getModel());
        System.out.println("차량 연도: " + car.getYear());
        System.out.println("원주율: " + PI);
    }
}

요약

  • PI는 상수이고, car는 불변 객체로, Vehicle 클래스는 final 클래스로 설계되어 상속이 불가능하고 객체의 상태가 불변임.

🎯 핵심 정리

  1. final 변수: 한 번 할당된 값을 변경할 수 없게 만듦.
  2. 상수: 값을 변경할 수 없는 변수. 보통 public static final로 선언.
  3. 불변 객체: 객체의 상태가 변경되지 않도록 설계된 객체. 내부 필드도 final로 선언하며, 값을 수정하는 메서드는 제공하지 않음.