백엔드 개발자라면 대답해야 할 100가지 질문

5. 자바에서 final의 기능은 무엇입니까?

ignuy 2023. 7. 24.

final은 사전적 의미와 마찬가지로 ‘마지막’이라는 의미를 지닌다. final을 통해 객체는 변경될 수 없는 성질(불변성)을 가지게 되고 final은 거의 모든 대상에 사용될 수 있다.

대상 의미
멤버변수 값을 변경할 수 없는 상수가 된다.
지역변수 값을 변경할 수 없는 상수가 된다.
클래스 변경(확장)될 수 없는 클래스를 의미하게 된다. 따라서 final 클래스는 다른 클래스의 조상이 될 수 없다.
메소드 변경(확장)될 수 없는 메소드를 의미하게 된다. final 메소드는 Override를 통해 재정의 될 수 없다.

+ 현업이나 대규모 프로젝트에 가면 기능 단위 메소드에 final 키워드를 통해서 더 이상의 변경을 금지하는 의미를 표현하기도 한다.

변수에 적용된 final

앞에 final이 붙은 변수는 초기화 후에 더이상 변경할 수 없다. 변경하게 되면 컴파일 에러가 발생하니 유의하자.

final String complieError = "final";
complieError = "Error"; // <- 컴파일 에러 발생

조금 특이한 형태로 argument에 final이 붙는 경우도 있다. 이 경우도 마찬가지로 메소드 내에서 인자값의 변경이 불가능하며 변경을 시도할 시 컴파일 에러가 발생한다.

클래스에 적용된 final

앞에 final이 붙은 클래스는 다른 클래스가 상속할 수 없는 클래스가 된다. 마찬가지로 상속을 시도하면 컴파일 에러가 발생한다. side-effect가 있으면 안 되는 자바 코어 라이브러리에서 final로 선언된 클래스를 쉽게 찾을 수 있을 것이다.

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
}

메소드에 적용된 final

final이 붙은 메소드는 더 이상 Override 할 수 없도록 한다. 마찬가지로 재정의를 시도하면 컴파일 에러가 발생한다. 구현한 코드가 상정된 의도 외에 변경되는 것을 원하지 않을 때 final을 사용한다. 메소드 또한 side-effect가 있으면 안 되는 자바 코어 라이브러리에서 final로 선언된 메소드를 쉽게 찾을 수 있을 것이다.

단,

변경이 불가능하다는 불변성은 그 변수가 직접 가르키는 값에 한정된다. 다른 객체를 참조하는 경우 참조하는 객체의 내부의 값은 변경이 가능하다. 티스토리 블로거 사바라다님이 친절히 들어주신 예시로 설명을 대체해본다.

public class Service {

  public void variableFinal() {

    final int value = 2;
    final Person person = new Person("사바라다", 29);

    System.out.println("value = " + value);
    System.out.println("person_1 = " + person);

		// value = 2; // 컴파일 에러
    person.setAge(10);
    person.setName("사바라");

    System.out.println("person_2 = " + person);
		// person = new Person("염광호", 29); // 컴파일 에러
  }
}

class Person {

  private String name;

  private int age;

	//.. get, set, toString 메서드 존재하나 길이 상 생략
}
value = 2
person_1 = Person{name='사바라다', age=29}
person_2 = Person{name='사바라', age=10}

위 코드를 다시 한번 설명하자면, 원시형 타입의 값과 참조형 타입이 가리키는 객체는 변경할 수 없지만 참조형 객체의 내부 값은 변경이 가능하다는 얘기이다.

댓글