[Java] final에 대해 알아보자!

이재표·2023년 9월 23일
0

Java

목록 보기
1/2

개발을 진행하며 무의식적으로 생성자 주입, 상수 선언 등에서 final 키워드를 사용하는데, 이것이 무엇인지...한번 알아보도록 하겠습니다!

final이란

Java에서 final이란 다음과 같이 설명하고 있습니다.

final은 자료형에 값을 단 한 번만 설정할 수 있게 강제하는 키워드이다. 값을 한 번 설정하면 그 값을 다시 설정할 수 없다.

'마지막'이라는 의미처럼 final은 재할당을 막아주는 키워드입니다. 따라서 재할당되어 변하는지 않을까?라는 불안감으로 여러 검증로직을 추가해야하는 상황을 막을수 있습니다. 그럼 final을 이용할때 고려해야하는 여러 상황에 대해 알아보도록 하겠습니다.

변수에 final을 사용할때

final String test_var = "test";
test_var = "change_test"; 
//java: cannot assign a value to final variable test_var

다음과 같이 변수에 final키워드를 작성할시 test_var에 할당이 불가하는 에러가 뜨는 것을 알수있습니다.

변수에 final을 이용하는 경우는 크게 두가지가 있는데 첫번째는 상수를 선언하기 위해 이용하는 경우이다. 변하지 않아야하는 상수의 경우 코드내에서 재할당 될시 로직상 문제가 일어날수 있는 여지가 많기 때문에 final을 통해 선언하며 보통 private static final형식으로 선언되는것을 알수 있습니다.

Class test(){
	private static final String test_var = "test";
}

static의 경우 같은 컴파일시 딱한번 메모리할당을 하기에 같은 값을 이용하기 위한 상수의 경우 final과 함께 사용시 효율성 측면에서 장점이 있다.

두번째째는 생성자의 인자로써 사용할수 있다.

Class test(final String test_var){
}

이렇게 사용할시 생성시 원하는 값을 넣고, 해당 클래스내에서 재할당 할수 없기때문에 값을 보장할수 있게된다.

void test(final String test_var) {
    test_var="change_test";
    //java: cannot assign a value to final variable test_var
}

메서드에 final을 사용할때

메서드에 final을 사용하게 되면 메서드를 재정의할수 없다는 뜻이다. 즉 자식 클래스가 부모 클래스의 메서드를 재정의하는 경우, 오버라이딩이 불가능해진다.

class ParentClass {
  final void finalMethod() {

  }
}

class ChildClass extends ParentClass {
  void finalMethod() {
    //java: finalMethod() in ChildClass cannot override finalMethod() in ParentClass
    //  overridden method is final
  }
}

다른 클래스에 메서드가 변하는 것을 원하지 않을때, 변경되면 안되는 메서드가 존재할때 final키워드를 통해 보장할수 있게된다.

클래스에 final을 사용할때

클래스에 final을 사용하게 되면 메서드와 비슷한 맥락으로 클래스를 재정의할수 없게된다는 뜻이다. 즉, final이 붙게되면 상속할수 없는 클래스가 된다는 의미이다.(부모 클래스가 되는것이 불가능하다)

final class ParentClass {
}
        
class ChildClass extends ParentClass {
  //java: cannot inherit from final ParentClass
}

대표적인 final 클래스는 String이 존재합니다. 자바의 자료형, 코어 라이브러리이기에 어떠한 변화가 생긴다면 상속하여 만든 새로운 클래스들의 실행을 보장하기 어려워지기에 상속이 불가하도록 막아두었습니다.

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

final == 상수?

글을 읽다보면 이러한 생각이 드실겁니다. "그러면 final을 이용하면 해당 변수는 변치않는 상수가 되는거네?"
물론 상수를 표현하기위해 private static final형태로 많이 이용하지만, 이것이 final이 불변을 의미하는것은 아닙니다.
맨처음 final의 사전적 정의를 보겠습니다.

final은 자료형에 값을 단 한 번만 설정할 수 있게 강제하는 키워드이다. 값을 한 번 설정하면 그 값을 다시 설정할 수 없다.

정의에서 표현된 설정은 할당을 의미합니다. 즉 final을 이용하면 재할당이 불가능하지, 값의 불변을 의미하는 것이 아닙니다. 예시를 보도록 하겠습니다.

public static void main(String[] args) {
  final List<String> test_var = new ArrayList<>(Arrays.asList("test1", "test2"));
  System.out.println(test_var);
  test_var.add("test3");
  System.out.println(test_var);
}


final을 불변이라 생각하면 다음과 같은 리스트에 값을 추가하는 불변을 망가뜨리는 메서드를 실행하면 에러가 나야합니다. 하지만 리스트의 값을 변하것을 보며 final만으로 값의 불변성을 지키지는 못하는것을 볼수 있습니다.

0개의 댓글