Java - final, finally, finalize의 차이점

JS · 18 Jul 2020

Java의 final, finally, finalize는 전혀 다른 내용이지만, 이름이 비슷하여 헷갈릴 수도 있습니다.

이 글에서는 다음 내용들이 무엇인지, 어떻게 사용하는지 알아보겠습니다.

  • final keyword
  • finally keyword
  • finalize method

1. final 키워드

final 키워드는 클래스, 메소드, 변수, 인자를 선언할 때 함께 사용할 수 있습니다. final를 사용하면, 공통적으로 각각의 상태를 유지하려는 특징을 갖고 있습니다.

final 변수

예를 들어, 다음과 같이 final을 사용하여 변수를 선언할 수 있습니다. final 키워드가 붙은 변수는 한번 초기화되면 그 이후에 변경할 수 없습니다. 만약 변경하려고 하면 컴파일 에러가 발생합니다.

final String hello = "Hello world";

hello = "See you around" // compile error!

final 메소드

다음과 같이 클래스의 메소드를 선언할 때 final을 사용할 수 있습니다.

class AAA {
    final String hello = "hello world";

    final String getHello() {
        return hello;
    }
}

final로 선언된 메소드는, 다른 클래스가 이 클래스를 상속할 때 메소드 오버라이딩을 금지합니다. 예를 들면, 다음과 같이 AAA 클래스를 상속하는 BBB 클래스에서는 getHello()를 재정의할 수 없습니다. Override하려고 하면 컴파일 에러가 발생합니다.

class BBB extends AAA {

    @Override
    String getHello() { // compile error !
        return "See you around";
    }
}

final 클래스

다음과 같이 final 키워드를 사용하여 클래스를 정의할 수 있습니다.

final class AAA {
    final String hello;
    AAA() {
        hello = "hello world";
    }
}

final으로 클래스를 선언하면, 다른 클래스에서 이 클래스를 상속할 수 없습니다. 만약 다음과 같이 final 클래스를 상속하려고 하면 컴파일 에러가 발생합니다.

class BBB extends AAA() { // compile error!
}

final에 대해서 더 자세히 알고 싶다면 Java - Final 키워드에 대한 이해를 참고해주세요.

2. finally 키워드

finally 키워드는 try-catch와 함께 사용됩니다. try-catch가 종료될 때 finally block이 항상 수행됩니다.

다음은 강제로 Exception을 발생시키는 코드입니다.

try {
  System.out.println("try block");
  throw new Exception();
} catch (Exception e) {
  System.out.println("catch block");
} finally {
  System.out.println("finally block");
}

결과는 다음과 같이 출력됩니다.

try block
catch block
finally block

catch가 없더라도 finally block은 항상 실행됩니다.

try {
    System.out.println("try block");
} finally {
    System.out.println("finally block");
}

Output:

try block
finally block

정리하면, finally block은 try block이 종료될 때 항상 실행됩니다. 그래서 사용이 모두 끝난 FileInputStream 등의 FileDescriptor를 닫을 때 사용되기도 합니다.

3. finalize 메소드

finalize()는 Object 클래스에 선언된 protected 메소드입니다. Java에서 모든 클래스는 Object 클래스를 상속하는데요. 그렇기 때문에 모든 객체는 finalize() 메소드를 갖고 있습니다.

Garbage collector가 어떤 객체를 참조하는 객체가 없다고 생각되면, 이 객체를 소멸시킵니다. 객체를 소멸시킬 때 finalize() 메소드를 호출해 줍니다.

package java.lang;

public class Object {
  ...

  protected void finalize() throws Throwable { }
}

클래스를 정의할 때 finalize()를 오버라이드 할 수 있습니다. finalize()는 소멸될 때 호출되기 때문에 어떤 자원을 함께 소멸해주도록 구현할 수 있는데요. 메소드 호출 시점이 Garbage collector에 의존적이기 때문에, 생각했던 타이밍과 다를 수 있습니다. 이런 이유로 finalize를 재정의하지 않는 것이 좋습니다.

정리

final, finally, finalize에 대해서 알아보고, 어떻게 사용되는지에 대해서 간단히 알아보았습니다.

댓글을 보거나 쓰려면 이 버튼을 눌러주세요.
codechachaCopyright ©2019 codechacha