final, finalize, finally의 차이와 활용

2025. 4. 1. 13:30·CS 스터디/CS - JAVA

final, finalize, finally는 자바를 처음 접할 때, 충분히 헷갈릴 수 있는 키워드 입니다. 각각의 특징을 코드와 함께 간단하게 살펴보겠습니다.

1. final


final 키워드는 값 변경, 상속, 오버라이딩을 제한하는 키워드입니다. 코드의 불변성을 보장하는데 사용되며, 코드의 의도를 명확히하고 안정성을 높이는데 유용합니다.

 

final 키워드는 기본적으로 변수, 메서드, 클래스에 사용할 수 있습니다. 각각의 사용법에 대해 알아보겠습니다.

 

1.1 final 변수 (변수 앞에 final이 붙은 경우)

final키워드가 붙은 변수는 값을 한 번만 할당할 수 없으며, 초기화 이후 값을 변경할 수 없습니다.

  • 특정 값을 고정적으로 사용하는 상수를 정의할 때 자주 사용됩니다. 일반적으로 네이밍 컨벤션을 대문자+언더스코어(_)로 사용하며, static과 함께 전역적으로 선언합니다.

final 변수 예시 코드

public class FinalVariableExample {
    // static final을 사용하여 클래스 상수 선언 (값 변경 불가)
    private static final int X = 10;

    public static void main(String[] args) {
        // X = 20; // ❌ 오류! (final 변수는 값을 변경할 수 없음)
        System.out.println(X);
    }
}

1.2 final 메서드 (메서드 앞에 final이 붙은 경우)

final을 메서드에 사용하면, 해당 메서드는 오버라이드(재정의)할 수 없습니다. 즉, 상위 클래스에서 정의된 final 메서드를 하위 클래스에서 오버라이딩할 수 없습니다.

  • 상위(부모) 클래스의 중요한 기능을 하위(자식) 클래스에서 변경하지 못하도록 보호할 때 사용됩니다.

final 메서드 예시 코드

class Parent {
    // final 메서드로 정의된 show 메서드
    final void show() {
        System.out.println("This is a final method.");
    }
}

class Child extends Parent {
    // void show() {  // ❌ 오류! (final 메서드는 오버라이딩 불가)
    //     System.out.println("Overriding not allowed.");
    // }
}

1.3 final 클래스 (클래스 앞에 final이 붙은 경우)

final 키워드가 붙은 클래스는 상속할 수 없습니다. 객체의 생성은 가능하지만, 확장은 불가능합니다.

  • 클래스의 상속을 원척적으로 차단하여, 클래스의 구현이 변경되는 것을 방지하는 데 사용됩니다.

final 클래스 예시 코드

final class Car { // final로 설정된 Car 클래스
    void drive() {
        System.out.println("Driving...");
    }
}

// class SportsCar extends Car {} // ❌ 오류! (final 클래스는 상속 불가)

public class FinalClassExample {
    public static void main(String[] args) {
        Car myCar = new Car(); // ✅ 객체 생성은 가능
        myCar.drive();
    }
}

 

2. finally


예외 (Exception) 발생 여부와 상관없이 일반적인 실행환경에서는 반드시 실행되는 코드 블록입니다. try-catch-finally 구조에서 사용되며, 코드의 안정성을 보장하기 위해 반드시 실행되어야 하는 작업(리소스 해제, 클린업)을 처리하는 데 사용됩니다.

 

try 블록 안에 예외가 발생하거나, return, break, continue가 있어도 finally블록은 실행됩니다.

finally 예시 코드

public class FinallyTest {
    public static void main(String[] args) {
        System.out.println(testMethod());
    }

    static int testMethod() {
        try {
            System.out.println("try 실행");
            return 10;  // ✅ return 문 실행
        } finally {
            System.out.println("finally 실행");  // ✅ return 전에 실행됨
        }
    }
}

출력 결과

finally 실행
try 실행

 

3. finalize


객체가 GC에 의해 제거되기 직전에 호출되는 메서드로 메모리에서 제거되기 전에 정리 작업을 수행할 수 있도록 설계된 메서드입니다.

하지만, JAVA 9부터 Deprecated되어 더 이상 사용이 권장되지 않습니다.

 

finallize()가 더 이상 사용이 권장되지 않는 이유

  1. System.gc()를 호출해도 GC가 바로 실행되지 않을 수 있어 객체 정리작업을 즉시 실행할 수 없습니다.
  2. GC가 객체를 제거할 때, finallize()를 거쳐 객체의 제거를 수행해야 하므로, 제거 동작의 오버헤드가 발생해 시스템의 성능이 저하될 수 있습니다.

 

finallize()를 대체할 수 있는 자원 해제 방법

일반적인 Java 개발 환경
  • try-with-resource : 자원을 명시적으로 닫는 코드를 작성하지 않고도, 안전하게 자원을 관리할 수 있도록 설계된 구문. AutoClosable 또는 Closable 인터페이스를 구현한 자원에 한해 사용가능하며, 자원을 자동으로 닫을 수 있도록 close() 메서드가 자동으로 호출됨. 주로 I/O 관련 클래스에서 이 인터페이스들을 구현
Spring 개발 환경
  • Spring은 외부 API를 제외한 대부분의 자원을 IoC(제어의 역전)와 DI(의존성 주입)를 활용하여, 자원의 관리를 자동화합니다. 대부분의 자원들을 Spring Container에서 자동으로 생성하고 관리하므로, Bean으로 등록된 객체들은 개발자가 close()메서드를 명시적으로 호출할 필요가 없습니다. 따라서 Spring이 관리하지 않는 자원을 제외하고는, try-with-resource조차 사용할 필요가 없습니다.

 

finalize 예시 코드

class MyResource {
    // 객체가 가비지 컬렉션에 의해 제거되기 직전에 호출되는 메서드
    @Override
    protected void finalize() throws Throwable {
        // 자원 정리 작업
        System.out.println("MyResource 객체가 가비지 컬렉션에 의해 제거되기 직전에 finalize()가 호출되었습니다.");
        super.finalize(); // 부모 클래스의 finalize() 메서드를 호출
    }
}

public class FinalizeExample {
    public static void main(String[] args) {
        MyResource resource = new MyResource(); // MyResource 객체 생성

        // 자원 정리를 위해 null로 설정하고 GC에 의한 객체 제거를 유도
        resource = null;

        // 가비지 컬렉션을 강제로 실행하도록 유도 (주의: GC는 즉시 실행되지 않음)
        System.gc();  // 강제로 가비지 컬렉션을 실행하라고 요청

        // 잠시 대기하여 finalize() 메서드 호출을 확인
        try {
            Thread.sleep(1000);  // 1초 대기
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

'CS 스터디 > CS - JAVA' 카테고리의 다른 글

equals()와 hashcode()  (0) 2025.04.08
Java의 예외처리  (0) 2025.04.07
String, StringBuilder, StringBuffer 특징 및 성능비교  (0) 2025.03.26
String 객체와 String 리터럴  (0) 2025.03.25
객체 지향 프로그래밍(OOP)의 특징 4가지  (0) 2025.03.22
'CS 스터디/CS - JAVA' 카테고리의 다른 글
  • equals()와 hashcode()
  • Java의 예외처리
  • String, StringBuilder, StringBuffer 특징 및 성능비교
  • String 객체와 String 리터럴
BIS's tech Blog
BIS's tech Blog
Welcome to Kanghyun's tech blog :)
  • BIS's tech Blog
    벼익숙의 기술 블로그
    BIS's tech Blog
  • 전체
    오늘
    어제
    • 분류 전체보기 (67)
      • 알고리즘 (53)
        • 백준 (44)
        • 프로그래머스 (9)
      • CS 스터디 (14)
        • CS - JAVA (11)
        • CS - DB (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    동적 계획
    깊이 우선 탐색
    완전탐색
    bottom-up
    백준
    Baekjoon
    dp
    java
    BFS
    Lv2
    브루트포스
    자료구조
    재귀
    Top-Down
    프로그래머스
    CS
    DFS
    너비 우선 탐색
    기술질문
    알고리즘 고득점 kit
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
BIS's tech Blog
final, finalize, finally의 차이와 활용
상단으로

티스토리툴바