Just Do It

[JAVA] static, final

by 핫도구
반응형

Java에서 매우 중요하고도 헷갈리기 쉬운 두 키워드인 static과 final이 존재한다.

static

static은 멤버(필드, 메서드)가 특정 객체(인스턴스)에 소속되는 것이 아니라 클래스 자체에 소속되도록 만든다. 이는 해당 클래스의 모든 인스턴스가 공유하는 멤버가 된다는 뜻이다. 메모리 관점에서 보면 인스턴스 멤버는 new 키워드로 객체가 생성할 떄마다 힙 영역에 각각 생성되지만 static 멤버는 자바 프로그래밍 시작될 때 메서드 영역에 한번만 생성된다.

static의 사용용도

1. static 변수(정적변수, 클래스 변수)
목적 : 클래스의 모든 인스턴스가 공통된 값을 공유해야할 경우 사용한다.
특징
- 인스턴스를 생성하지 않고도 클래스이름.변수명으로 접근할 수 있다.
- 모든 인스턴스가 하나의 저장 공간을 공유하므로 한 곳에서 값을 변경하면 모든 인스턴스에 영향을 준다.

class Car {
    public static int totalCars = 0;
    public String name;

    public Car(String name) {
        this.name = name;
        totalCars++;
    }
}

public class CarTest {
    public static void main(String[] args) {
        System.out.println("생성전 전체 차의 수 : "+Car.totalCars); // 0

        Car car1 = new Car("hyundai");
        System.out.println("car1 생성 후 전체 차의 수 : "+Car.totalCars); // 1 클래스이름.변수명으로 접근

        Car car2 = new Car("benz");
        System.out.println("car2 생성 후 전체 차의 수 : "+Car.totalCars); // 2
    }
}

 

2. static 메소드(정적 메서드 또는 클래스 메서드)
목적 : 인스턴스 상태(멤버 변수)와 상관없이, 기능 자체만으로 동작하는 유틸리티 서역의 메서드를 만들 때 사용한다.
특징
- 인스턴스를 생성하지 않고 클래스이름.메서드이름()으로 호출할 수 있다.
- static 메서드 내부에서는 인스턴스 변수나 this 키워드를 사용할 수 없다. static 멤버는 인스턴스 생성 없이도 존재할 수 있지만, 인스턴스 멤버는 인스턴스가 있어야만 존재하기 때문이다.

class MathUtil {
    public static int add(int a, int b) {
        return a + b;
    }
}

public class MathUnitTest {
    public static void main(String[] args) {
        
        // 객체 생성 없이 바로 메서드 호출
        int result = MathUtil.add(4,6);
        System.out.println("결과 = "+result); // 10
    }
}

 

3. 초기화 블럭
목적 : static 변수를 복잡한 로직으로 초기화해야 할 때 사용한다.
특징
- 클래스가 메모리에 로딩될 떄 단 한번 실행된다.

class StaticBlockExample {
    public static int number;
    public static String text;
    static {
        System.out.println("Static 블록이 실행됩니다.");
        number = 100;
        text = "Initialized";
    }
}

public class StaticBlockTest {
    public static void main(String[] args) {
        System.out.println("main 메소드 시작");
        System.out.println(StaticBlockExample.number);
        System.out.println(StaticBlockExample.text);
    }
}
//main 메소드 시작
//Static 블록이 실행됩니다.
//100
//Initialized

 

4. static 중첩 클래스(Nested Class)
클래스 내부에 static 키워드를 사용하여 클래스를 선언할 수 있으며 외부 클래스의 인스턴스 없이도 독립적으로 인스턴스화 할 수 있는 클래스를 만들 떄 사용된다.

 

final

final이 어디에 붙느냐에 따라 그 역할이 달라지며 각각 변수, 메서드, 클래스에 붙을 수 있다.

1. final 변수
단 한번만 초기화할 수 있는 상수를 만들 때 사용된다.
특징
- 선언과 동시에 초기화하거나, 생성자에서 단 한번만 초기화할 수 있다.
- 초기화된 이후에는 값을 변경할 수 없다.

public class FinalVariable {
    // 선언과 동시에 초기화
    final int MAX_SIZE = 100;
    
    // 생성자에서 초기화
    final String NICKNAME;
    
    // 참조변수에 final 사용
    final StringBuilder sb = new StringBuilder("Hello");
    
    public FinalVariable(String nickname) {
        this.NICKNAME = nickname;
    }
    
    public void test() {
//        MAX_SIZE = 200; // 컴파일 에러, FINAL 변수는 수정 불가
        
//        sb = new StringBuilder("World"); // 다른 객체를 참조할 수 없음
        
        sb.append(" World"); // 객체 내부의 상태는 변경이 가능
        System.out.println(sb.toString()); // Hello World
    }
}

 

2. final 메서드
목적 : 하위 클래스에서 이 메서드를 오버라이딩 하는 것을 방지하고 싶을 경우 사용한다.
특징
- 핵심적인 로직이 변경되어서는 안되는 중요한 메서드에 사용한다.

public class Parent {
    public final void showMessage() {
        System.out.println("이 메세지는 변경할 수 없습니다.");
    }
}

class Child extends Parent {
    // public void showMessage() {}; // final 메서드는 오버라이딩이 불가하다.
}

 

3. final 클래스
목적 : 이 클래스를 상속하는 것을 방지하고 싶을 경우에 사용한다.
특징
- 보안상의 이유나, 클래스의 구현이 완전하여 더이상 확장될 필요가 없을 떄 사용한다.
- 대표적으로 String, Integer 클래스가 있다.

final class SecureString {
}
//class MyString extends SecureString { } // final 클래스는 상속 불가

 

궁극의 상수인 static final

static과 final을 함께 사용하면 공유 가능하고 변경이 불가능한 상수를 만들 수 있다. 이는 프로그램 전체에서 유일하며 변하지 않는 값을 정의할 때 매우 유용하다.
일반적으로 이를 정의할 때 변수명은 _를 사용하여 작성한다,(MAX_VALUE)

class Constants {
    public static final double PI = 3.141592;
    public static final int MAX_USERS = 1000;
    public static final String APP_NAME = "My Awesome App";
}

public class ConstantTest {
    public static void main(String[] args) {
        System.out.println("원주율 : "+Constants.PI);
        // Constants.PI = 3.21; // 컴파일 에러
    }
}

  static final
핵심 의미 클래스에 속하는, 공통의 최종적인, 변경 불가능한
주요 목적 모든 인스턴스가 공유하는 멤버 정의 값/메서드/클래스 변경 방지
메모리 메서드 영역(클래스 로딩시 1회) 스택 또는 힙 영역(인스턴스 생성 시)
사용 대상 변수, 메서드, 초기화 블록, 중첩 클래스 변수, 메서드, 클래스
변경 가능성 값 변경 가능 값/구현/상속 변경 불가능

추가적으로 public static final로 선언된 상수의 경우 대문자로 작성하는 것이 굉장히 권장된다.


이처럼 static은 공유의 개념으로 여러 인스턴스가 함께 사용해야 하는 자원을 관리할 떄 사용하며 final은 불변의 개념으로 코드의 안정성과 예측 가능성을 높이고 싶을 때 사용한다.
이 두 키워드의 차이점과 용도를 명확하게 알고 사용해야 한다. 다음에는 생성자와 this에 대해 알아 볼 예정이다.

반응형

'JAVA > BASIC' 카테고리의 다른 글

[JAVA] 상속  (4) 2025.08.03
[JAVA] 생성자와 this  (3) 2025.08.02
[JAVA] 접근제어자  (4) 2025.07.31
[JAVA] 클래스와 객체  (4) 2025.07.30
[JAVA] 객체지향프로그래밍이란?  (2) 2025.07.29

블로그의 정보

AquaMan

핫도구

활동하기