코딩 공부/Java

[Java] Chpater 2- 05) final - 변하지 않는 값

sintory-04 2025. 2. 25. 17:33

    1️⃣ final 이란?

    1. 변수는 변경이 불가능하게 만든다

    • 변수에 final 을 붙이면 변수를 한 번만 설정할 수 있습니다.
    final int a = 100;
    a = 200; // ❌ 오류 발생!

    2. 클래스는 상속할 수 없게 만든다

    • final 로 선언된 클래스는 상속할 수 없습니다.
    final class Animal {
        void sound() {
            System.out.println("Animal sound!");
        }
    }
    
    // class Dog extends Animal {} // ❌ 오류! final 클래스는 상속할 수 없음

    3. 메서드는 수정할 수 없게 만든다(오버라이딩 불가)

    • final 로 선언된 메서드는 오버라이딩 할 수 없습니다. (오버라이딩은 추후에 학습합니다.)
    class Parent {
        final void show() {
            System.out.println("Hello from Parent");
        }
    }
    
    class Child extends Parent {
    
            @Override
        void show() { // ❌ 오류! final 메서드를 재정의할 수 없음
            System.out.println("Hello from Child");
        }
    }

    2️⃣ 상수

    • 상수는 변하지 않고 항상 일정한 값을 갖는 수 이다.
    • Java에서 상수는 대문자로 표현하는 것이 관례
    • 프로그램 실행중에 절대 변경돼서는 안 되기 때문에 static final 키워드를 사용해 선언한다.
    • static 으로 선언된 변수는 프로그램 시작시 한 번만 초기화되고 모든 인스턴스에서 같은 값을 공유한다.

    - 예시를 들자면 아래와 같은 원주율을 들 수 있다.

    public class Circle {
    
        final static double PI = 3.14159; // ✅ 상수 선언
    }
    System.out.println("상수활용: " + Circle.PI);
    • 보다시피, static 으로 선언한 것을 알 수 있다.
    • 보통 상수는 여러 곳에서 값을 공유해 쓰일 목적으로 활용된다.
    • 인스턴스 변수를 static 없이 선언할 경우 인스턴스마다 PI 값이 중복 저장되기 때문에, Static 으로 선언해주어야 한다.

    3️⃣ 불변객체(Immutable Object)

    1. 불변객체(Immutable Object) 의 특징

    • 불변객체는 내부 상태를 변경할 수 없는 객체입니다.
    • final 을 속성(property, field) 에 활용합니다.
    • 세터(setter) 없이 설계 합니다.
    • 변경이 필요할 경우 새로운 객체를 만들어야 합니다.
    • 예) String , Integer , 래퍼클래스

    2. 잘못된 불변객체 사용

    • final 은 참조 변경을 막지만 내부상태 변경은 막지 않습니다.
    public class Circle {
    
        final static double PI = 3.14159; // ✅ 직접 만든 원주율 상수
        double radius; // ⚠️ final 로 선언되어 있지 않기 때문에 외부에서 변경 가능
    
        Circle(double radius)  {
            this.radius = radius;
        }
    }
    
    final Circle c1 = new Circle(2);
    c1 = new Circle(3); // ❌ final은 변수 c1이 한 번 참조한 객체는 다른 객체로 변경될 수 없음을 의미함 (참조 불변)
    
    // 하지만 객체 내부의 속성 값은 변경 가능 (불변 객체가 아님)
    c1.radius = 3; // ⚠️ 내부 상태 변경 가능 (객체 자체가 불변이 아님)
    

    3. 올바른 불변 객체 활용

    • 속성을 final 로 선언해 준다.
    public final class Circle { // ✅ 클래스에 final 선언 (상속 방지)
    
    private static final double PI = 3.14159; // ✅ 상수는 private static final로 선언  
    private final double radius; // ✅ 필드를 private final로 선언하여 완전한 불변성 유지
    
    public Circle(double radius) { // ✅ 생성자는 public으로 유지  
    this.radius = radius;  
    }
    
    public double getRadius() { // ✅ public 메서드로 변경  
    return radius;  
    }
    
    public double getArea() { // ✅ public 메서드로 변경  
    return PI \* radius \* radius;  
    }
    
    public double getPerimeter() { // ✅ public 메서드로 변경  
    return 2 \* PI \* radius;  
    }
    

    4. 불변 객체의 값을 변경하고 싶을 시,

    • 불변성을 유지하면서 값을 변경하는 효과를 얻을 때 활용
    • 기존 객체의 상태를 직접 변경할 수 없기 때문에 새로운 객체를 생성
    • 생성자를 새로 호출하거나 아래의 기능을 활용할 수 있다.
    public final class Circle {
        public static final double PI = 3.14159;
        private final double radius;
    
        public Circle(double radius) {
            this.radius = radius;
        }
    
        // ✅ 반지름이 다른 새로운 Circle 생성 (불변 객체 유지)
        public Circle changeRadius(double newRadius) {
            return new Circle(newRadius); // 생성자 호출: 기존 객체 변경 X, 새 객체 생성
        }
    }