개발 기록

>[Java] static, final, 상수 개념과 사용 본문

JAVA

>[Java] static, final, 상수 개념과 사용

1z 2020. 7. 19. 18:20

 

1. Static   

 

static 은 '고정된' 이란 의미를 가지고 있다. 객체(인스턴스)에 소속된 멤버가 아니라 클래스에 소속된 멤버이기 때문에 클래스 멤버라고도 한다. 정적 필드와 정적 메소드는 클래스에 고정된 멤버이므로 클래스 로더가 클래스(바이트코드)를 로딩해서 메소드 메모리 영역에 적재할 때 클래스별로 관리된다. 따라서 클래스의 로딩이 끝나면 바로 사용할 수 있다.

 

(1) 특징

 인스턴스에 종속되지 않음

클래스 멤버로 사용: 인스턴스 생성 없이 클래스 이름으로 직접 접근할 수 있는 클래스 변수(static variable) 또는 클래스 메서드(static method)를 생성

메모리 공간: static 필드는 클래스가 로드될 때 생성되어 프로그램의 생애 주기 동안 유지된다.

인스턴스 변수 접근 불가: static 메서드 내부에서는 인스턴스 변수에 직접 접근할 수 없다.=> 인스턴스 생성 후에만 접근 가능

클래스 로드시 초기화

공유 데이터와 유틸리티 기능 제공 ex. Math 클래스의 메서드들은 모두 static으로 정의되어 있다.

static 데이터는 toString()메서드를 추가할 때 자동으로 처리되지 않는다.

 

(2) 사용    

클래스가 메모리로 로딩되면 정적 멤버를 바로 사용할 수 있는데, 클래스 이름과 함께 도트(.) 연산자로 접근한다.

클래스.필드;
클래스.메소드(매개값,...);

 

1. 정적 변수 (Static Variables)

모든 인스턴스가 공유하는 변수로 클래스 로드 시 초기화되고 프로그램 실행 중에 메모리에 상주한다.

public class Counter {
    public static int count = 0; // 정적 변수
}

// 정적 변수 호출
int result = Counter.count;

 

2. 정적 메서드 (Static Methods)

static 키워드로 선언된 메서드는 클래스 메서드(static method)로서 인스턴스 생성 없이 호출한다. 주로 유틸리티 기능을 제공하거나 객체 생성 없이 실행할 수 있는 메서드를 구현할 때 사용된다. 

public class MathUtils {
    public static int add(int a, int b) { // 정적 메서드
        return a + b;
    }
}

// 정적 메서드 호출
int result = MathUtils.add(10, 20);

 

3. 정적 블록 (Static Initialization Blocks)

인스턴스 필드는 생성자에서 초기화 하지만, 정적 필드는 객체 생성 없이도 사용해야 하므로 생성자에서 초기화 작업을 할수 없다. 그래서 정적 필드의 복잡한 초기화 작업을 위해서 정적 블록을 제공한다. 정적 블록은 클래스가 메모리로 로딩 될때 자동적으로 실행된다.

public class StaticExample {
    public static int number; // 정적 변수

// static 키워드를 사용하여 정적 초기화 블록 정의
    static { // 정적 초기화 블록
        number = 100;
        System.out.println("Static block initialized.");
       
// 내부에 인스턴스 필드, 인스턴스 메소드 사용불가
// this 키워드 사용 불가
    }
}

 

4. 중첩 클래스 (Static Nested Class)

다른 클래스 내부에 정의된 클래스로, 외부 클래스의 인스턴스와 무관하게 사용할 수 있다.

* Java 에서는 최상위 클래스를 static 으로 선언하는 것을 허용하지 않는다 . 클래스(중첩 클래스) 내의 클래스만 static 으로 만들 수 있다 .

 

★ 아래 예제는 static 중첩 클래스를 사용하여 싱클톤을 구현한 예제이다.

public class Singleton  {
// private 생성자로 외부에서 인스턴스 생성을 막음
    private Singleton() {}

// static 중첩 클래스에 싱글톤 인스턴스를 보관
    private static class SingletonHolder {
    // JVM에 의해 클래스 로딩 시점에 초기화됨
        public static final Singleton instance = new Singleton();
    }

   // 외부에서 접근 가능한 getInstance 메서드를 통해 인스턴스 반환
    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
}

 

외부 클래스와 강한 연관성이 있지만, 인스턴스화할 필요가 없는 보조 클래스를 정의할 때 사용한다.(car-engine)

외부 클래스의 인스턴스 멤버에 접근할 필요가 없을 때 사용하며, 이로 인해 외부 클래스와의 결합을 피하고 메모리 사용을 최적화한다.


2. Final  

final 키워드는 변수, 메서드, 또는 클래스에 사용될 수 있으며, 변수의 불변성, 메서드의 불변성, 클래스의 상속 제한 등을 명시적으로 표현하여 코드의 예상 동작을 보장하고 오류를 방지할 수 있다.   

 

(1) final 변수(상수) 

final 변수는 한 번 초기화되면 프로그램 실행 도중 다른 값으로 변경할 수 없는 상수가 된다.

② 초기화는 변수 선언 시에 직접 할 수도 있고, 생성자에서도 할 수도 있다.

* 단순 값이라면 필드 선언시 지정! 복잡한 초기화 코드거나 객체 생성시에 외부 데이터로 초기화해야 한다면 생성자에서 초기값을 지정!

* 만약 초기화 되지 않은 final 필드를 그대로 남겨두면 컴파일 에러가 발생한다. 

③ final 변수는 관례적으로 대문자와 언더스코어(_)를 사용하여 이름을 지정한다 (예: MAX_SIZE, PI).

④ static final 변수는 클래스 상수로 사용되며, 클래스의 모든 인스턴스에서 공유된다. 

public class Constants {
	// 클래스 변수
    public static final double PI = 3.14159;
 	// 인스턴스 변수
    public final int MAX_SIZE;

    public Constants(int maxSize) {
        this.MAX_SIZE = maxSize;
    }
}

 

 

★ final vs static final

일반적으로 불변의 값을 상수라고 부른다. (ex.불변의 값: 원주율 파이, 지구의 둘레 등) 

이런 불변의 값을 저장하는 필드를 자바에서는 상수라고 한다. final 필드는 한번 초기화 되면 수정할 수 없는 필드라고 하는데 finale필드를 상수라고 불러도 되지 않을까? 결론부터 말하자면 안된다. 

불변의 값은 객체마다 저장할 필요가 없는 가용성을 띠고 있으며, 여러가지 값으로 초기화 될 수 없기 때문이다. 반대로 final 필드는 객체마다 저장되고, 생성자의 매개값을 통해서 여러가지 값을 가질 수 있기 때문에 상수가 될수 없다.

상수는 static 이면서 final 이어야 한다. static final 필드는 객체마다 저장되지 않고, 클래스에만 포함된다. 그리고 한번 초기값이 저장되면 변경할수 없다.

 

 

(2) final 메서드  

final 메서드는 하위 클래스에서 오버라이딩할 수 없는 메서드를 나타낸다.  

:메서드 오버라이딩을 방지하여 메서드의 동작이 변경되지 않도록 보장한다.

메서드 앞에 final 키워드를 사용하여 선언한다.

public class Parent {
    public final void printMessage() {
        System.out.println("Parent's message");
    }
}

public class Child extends Parent {
    // 오버라이딩 시 컴파일 에러 발생(final 메서드는 오버라이드할 수 없음)
    // public void printMessage() { ... }
}

 

(3) final class

final 클래스는 상속할 수 없는 클래스를 나타낸다. 즉, 하위 클래스를 만들 수 없다.

: 보안, 성능, 최적화, 설계상의 이유로 클래스를 상속할 수 없도록 할 때 사용한다.

클래스 앞에 final 키워드를 사용하여 선언한다.

public final class UtilityClass {
    // 유틸리티 클래스 코드
}

 

 

 

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

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