ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java 의 Final 키워드
    언어/자바 2022. 5. 10. 21:08

     

    개요

    상속을 통해 기존 코드를 재사용할 수 있지만 때때로 다양한 이유로 확장성에 제한을 설정해야 합니다. final 키워드를 사용하면 정확히 그렇게 할 수 있습니다.

    Final Classes

    final 로 선언된 클래스는 상속될 수 없습니다. Java 핵심 라이브러리의 코드를 보면 많은 final 클래스들을 볼 수 있습니다. 대표적인 예시로는 String 클래스가 있습니다. 아래의 코드를 살펴보면 Cat 클래스는 final 로 선언되어 있고 이 클래스를 BlackCat 이 상속받고 있습니다. 그 결과 final 클래스인 Cat 을 상속받았다는 컴파일 에러가 발생한 것을 확인할 수 있습니다.

    @Getter
    @Setter
    public final class Cat {
      private int wieght;
    }
    public class BlackCat extends Cat {
      
    }
    The type BlackCat cannot subclass the final class Cat

    Final 키워드를 사용함으로써 오해하게 되는 것 중 하나는 final로 선언한 클래스의 객체가 immutable 이라고 생각하게 되는 것입니다. 하지만 객체의 속성을 자유롭게 바꿀 수 있습니다.

    Cat cat = new Cat();
    cat.setWeight(1);
    ​
    assertEquals(1, cat.getWeight());

    좋은 디자인의 규칙을 엄격하게 따른다면 클래스를 신중하게 만들고 안전상의 이유로 final로 선언해야 합니다. 그러나 final 클래스를 생성할 때는 주의해야 합니다.

    클래스를 final로 만든다는 것은 다른 어떤 프로그래머도 해당 클래스를 향상시킬 수 없다는 것을 의미합니다. 예를들어 어떤 클래스를 사용하공 ㅣㅆ는데 이에 대한 소스코드도 없는데 해당 클래스의 메소드 중 하나가 문제가 있는 메소드라고 가정해보겠습니다. 만약 해당 클래스가 final 이 아니면 해당 클래스를 상속받아서 override 하는 방법이 있겠지만 final 로 선언되어있기 때문에 해당 메소드를 override 할 수 없습니다. 클래스가 final이면 메서드를 재정의하고 문제를 해결하기 위해 클래스를 확장할 수 없습니다. 즉, 객체지향 프로그래밍의 장점 중 하나인 확장성을 잃게 됩니다.

    Final Methods

    final 로 선언된 메서드는 override 할 수 없습니다. 클래스를 구성할 때 어떤 메소드가 override 되면 안될 거 같을 땐 final 로 만들면 됩니다. 자바 코어 라이브러리에도 여러 메소드 들이 final 로 구성되어 있습니다. 대표적으로 Thread 클래스에 isAlive() 메소드가 final 로 선언되어 있습니다.

    public class Dog {
      public final void sound() {
        //...
      }
    }
    public class BlackDog extends Dog {
      public void sound() {
        
      }
    }

    위의 코드를 살펴보면 Dog 클래스의 sound() 메소드를 final 로 선언한 것을 볼 수 있습니다. 이 때 BlackDogDog 클래스를 상속하여 sound() 메소드를 override 할 수 있도록 선언해보겠습니다.

    해당 코드를 컴파일 하면 아래와 같은 오류가 뜨는것을 확인할 수 있습니다.

    Cannot override the final method from Dog sound() method is final and can’t be overridden

    Final Variables

    변수가 final 로 선언되면 다시 선언될 수 없습니다. 즉, final 변수가 초기화 되면 다른 값으로 변할 수 없습니다.

    Final Primitive Variables

    primitive 타입 중 하나인 int를 사용해 변수 i 를 선언해보겠습니다.

    public void whenFinalVariablesAssign_thenOnlyOnce() {
      final int i = 0;
      // ...
      i = 2;
    }

    결과로 아래와 같은 오류 메시지를 볼 수 있습니다.

    The final local variable i may already have been assigned

    Final Reference Variables

    reference 변수가 final 로 선언되면 마찬가지로 재 할당될 수 없습니다. 하지만 객체가 immutable 하다는 의미가 아닙니다. 객체의 속성값은 자유롭게 바꿀 수 있습니다.

    final Cat cat = new Cat();
    cat.setWeight(5);
    cat.setWeight(10);
    cat = new Cat(); // compile erro

    Final Fields

    final 로 설정한 필드는 상수가 될 수도 있고 선언된 후 바꿀 수 없는 필드일 수도 있습니다. 네이밍 컨벤션으로 클래스 상수는 대문자여야 하고 각 단어는 _ 로 이어져야 합니다.

    static final int MAX_WIDTH = 999;

    모든 final 필드는 생성자가 선언되기 전에 초기화 되어야 합니다.

    static final 필드는 다음과 같은 상황에서 초기화 될 수 있습니다.

    • 위의 예시들 처럼 선언할 때
    • static 초기화 블록에서

    final 필드는 다음과 같은 상황에서 초기화 될 수 있습니다.

    • 선언할 때
    • 생성자 안에서
    • 인스턴스 초기화 블록에서

    그 외의 경우엔 컴파일 에러가 발생합니다.

    Final Arguments

    finalarguments 앞에 붙일 수 있습니다. 이 경우 파라미터로 받은 argument는 메서드 안에서 수정될 수 없습니다.

    public void methodWithFinalArguments(final int x) {
      x = 1; // complie error
    }

    다음과 같이 수정하면 아래와 같은 에러 메시지를 볼 수 있습니다.

    The final local variable x cannot be assigned. It must be blank and not using a compound assignment
    ​

    참고

    https://www.baeldung.com/java-final

    '언어 > 자바' 카테고리의 다른 글

    인터페이스  (0) 2022.05.04

    댓글