final 과 객체의 불변성

final

: 마지막의, 변경될 수 없는

변수에 사용했을 시

  • 값을 변경 할 수 없는 상수가 된다.
    상수이므로 선언과 동시에 초기화를 한다.
    한번 입력한 값이 최종값 (static은 변경이 되더라도 항상 서로 같은 값을 share 개념)

  • 혹은 인스턴스 변수의 경우는 생성자에서 초기화가 가능하다.
    (상수지만 선언만 한 뒤, 생성자에서 단 한번만 초기화를 한다)
    ( 이 기능을 활용하면 각 인스턴스마다 final이 붙은 멤버변수가 다른 값을 갖도록 하는 것이 가능하다 → 각자 생성자를 호출하니까)

public class Shop{

  final int closeTime = 21;  //final 필드에 값을 저장하는 방법1 : 선언과 함께 초기화
  final int openTime;        //final 필드에 값을 저장하는 방법2 : 선언후 생성자에서 초기화

  public Shop(int openTime){
    this.openTime = openTime;
  }
}

객체에 사용했을 시

final 키워드는 값을 바꿀 수 없지만, 객체 일 경우에는 약간 다르다.
만약 객체인 ArrayList 가 있다면 값을 고치는게 가능하다.
그 이유는 final(상수) List 는 ArrayList 값을 지니고 있는 것이 아니고 ArrayList 객체의 주소를 참조하고 있기 때문이다.
그렇기 때문에 final 키워드로 ArrayList 의 주소가 변경이 불가능하게 할 뿐이다.

결국 Collection 에서 final은 재할당이 불가능한 것이고 추가,삭제가 불가능한 것이 아니다.

그렇다면 First Class Collection 은 왜 이야기가 나오는 것일까?

객체지향적 관점에서 우리는 객체들의 값이 바뀌지 않는다는 보장이 생겨야 코드를 수정하는 사이드 이펙트가 최소화될 수 있다.
하지만 Collection 에서 final은 값의 불변이 아닌 재할당이 불가능한 것이라고 했다.
때문에 First Class Collection 을 통하여 Collection 에 불변성을 부여하는 것이다. [일급컬렉션이란?]

public class Cars {
    private final List<Car> cars = new ArrayList<>();
    
    //가능 (객체 필드(속성)는 변경이 가능함)
    cars.add("AAA");
    cars.add("BBB");
    cars.get(0).change("CCC");
    
    //불가능 (다른 객체로 변경 할 수 없음 = 참조값 변경 불가)
    cars = new ArrayList<>();
}

메서드에 사용했을 시

  • 오버라이딩을 통해 재정의 될 수 없다.

클래스에 사용했을 시

  • 상속 클래스, 자신의 자손 클래스를 정의하지 못하게 된다.

static final

static final = "공통적인/고정된" + "최종적인"

  • final 의 경우 생성자에서 초기화를 하게 되는 경우라면 객체마다 다른 값들을 가질 수 있다. (변경이 안될뿐) 그러므로 final 자체만으로는 온전한 상수를 의미할 수 없다.
  • 하지만 static을 붙이게 되면 이미 공유되는 변수(메모리에서 유일한 변수) 이므로,
    객체마다 다른 값들을 가질 수 없고 + final 이므로 값에 대한 수정도 불가능하다.


미션 피드백 Review


[참조]
https://gobae.tistory.com/3
https://m.blog.naver.com/kiho0530/150143859108
https://advenoh.tistory.com/13

좋은 웹페이지 즐겨찾기