본문 바로가기

Back-end/Java

[Java] Static 개념 / 메모리 / 장단점

✅ Static이란

Static은 '고정된'이란 뜻이며 정적이라고도 부른다. 클래스, 변수, 메서드에 static을 붙이면 말 뜻대로 고정된 클래스, 변수, 메서드가 된다. ( static 멤버 = 정적 멤버 )

 

정적 클래스는 생성자를 포함할 수 없고, 모든 멤버는 static으로 선언해야 한다.

 

정적 변수 정적 메소드는 어떤 객체에 소속되지 않고, 클래스에 고정되어 있다. 객체에 소속되지 않으므로 객체 생성 없이 사용할 수 있다.
또한, 정적 메서드 내에서는 인스턴스 변수를 사용할 수 없다.

 

Static이 붙은 변수나 메서드는 객체를 생성하지 않고도 사용할 수 있다

 

 

 

✅ 예제 코드

public class StaticExample {

    // 정적 변수 (모든 인스턴스가 공유)
    static int staticVariable = 0;

    // 정적 메서드 (클래스를 통해 직접 호출 가능)
    static void staticMethod() {
        System.out.println("This is a static method.");
        System.out.println("Static variable in staticMethod: " + staticVariable);
    }

    // 인스턴스 변수 (각 객체가 개별적으로 가짐)
    int instanceVariable;

    // 생성자
    public StaticExample(int instanceVariable) {
        this.instanceVariable = instanceVariable;
        staticVariable++;  // 인스턴스 생성될 때마다 정적 변수 증가
    }

    // 인스턴스 메서드 (객체가 있어야 호출 가능)
    public void display() {
        System.out.println("Instance variable: " + instanceVariable);
        staticMethod(); // 정적 메서드는 인스턴스 메서드 안에서 사용 가능
    }

    public static void main(String[] args) {
        StaticExample.staticMethod();  // 클래스명으로 정적 메서드 호출

        StaticExample instance1 = new StaticExample(1);
        StaticExample instance2 = new StaticExample(2);

        instance1.display();  // 객체마다 다른 instanceVariable 출력
        instance2.display();

        // 정적 변수는 모든 인스턴스가 공유
        System.out.println("Static variable after instances created: " + StaticExample.staticVariable);
    }
}

 

 

✅ 코드 결과

 

This is a static method.
Static variable in staticMethod: 0

Instance variable: 1
This is a static method.
Static variable in staticMethod: 2

Instance variable: 2
This is a static method.
Static variable in staticMethod: 2

Static variable after instances created: 2

 

 

🔍 설명:

  • staticVariable: 클래스에 속한 변수이기 때문에 instance1, instance2가 공유합니다.
    • 생성자 호출될 때마다 staticVariable++ → 2까지 증가
  • staticMethod(): 클래스 이름으로 직접 호출 가능
  • display()는 인스턴스 메서드이므로 instance1.display()처럼 객체가 있어야 호출 가능
  • staticMethod()는 인스턴스 없이도 실행되므로 내부에서 instanceVariable은 접근 불가

 

✅ Static 멤버의 메모리 저장위치

일반적으로 우리가 new 연산을 통해 생성한 객체는 Heap 영역에 생성된다. 그리고 전역변수와 Static이 붙은 멤버들이 올라갈 수 있는 Static 메모리 공간이 따로 있다.

컴파일러는 Static이 붙은 변수, 메서드, 클래스들을 프로그램 실행과 동시에 Static 메모리 공간에 다 적재시킨다.

new 연산을 통해 객체를 생성하지 않아도 이미 컴파일러가 메모리 공간에 적재를 시킨 것이다.

그렇기 때문에, 우리가 new를 하지 않아도 Static 멤버에 접근할 수 있는 것이다.

Heap 메모리 공간은 GC를 통해 수시로 관리 되지만, Static 메모리 공간은 GC의 관리 영역 밖에 존재하므로 프로그램이 종료될 때까지 지워지지 않는다.


전역 변수 = Static 변수 ?
전역 변수는 일반적으로 프로그램 전체에서 사용되는 변수를 의미하지만, static 변수는 클래스 수준에서 사용되며 클래스 내에서 전역적으로 공유된다. 따라서 static 변수는 클래스 변수라고도 불리며, 전역 변수와는 약간 다른 개념이다.

 

 

✅ Static 사용을 지양해야 될 때

 

하지만, 프로그램이 종료될 때까지 메모리가 할당된 채로 존재한다는 것은 프로그램 성능에 영향을 줄 수 있다. 또한, 객체의 특정 상태를 사용해야 할 때는 Static을 사용할 수 없어서 객체지향적이지 않다고 말한다.

 

public class UserIdManager {
   private static int userId;

   public UserIdManager() { //생성자
       userId = 0;  
   }

   public static int generateUserId() {
       return userId++;
   }
}

 

 

위의 코드는 Static을 부적절하게 사용한 코드의 예시다.

이 클래스는 사용자 별로 할당되는 아이디를 관리하는 역할을 하려 하는데, userId가 static으로 선언되었기 때문에, 이 변수는 클래스 수준에서 공유된다. 이로 인해 여러 UserIdManager 인스턴스를 생성해도 userId는 하나만 존재하게 된다.

생성자에서 userId를 초기화하고 있지만, 이 생성자는 호출되지 않는다. 왜냐하면 generateUserId 메서드가 호출될 때마다 userId가 초기화되기 때문이다. 따라서 인스턴스 변수로 사용자 ID를 관리하는 것이 더 적절하다.

 

 

Static 사용해야 될 때

Static을 사용해야 할 때는 여러 객체 간에 데이터를 공유하고자 할 때이다. 이때, Static을 사용하면 해당 클래스의 모든 인스턴스에서 동일한 값을 공유할 수 있다. 또한, 매번 인스턴스를 생성하지 않아 속도가 빠르고, 낭비되는 메모리를 줄일 수 있다.

따라서, Static을 남용하지 않아야 하고, 사용 의도를 정확히 알고 사용한다면 가독성이 좋고 효율적인 코딩을 할 수 있다 !

 

✏️ 공부한점

결국 Static을 쓰는 이유는 다음과 같다

 

  • 공용 데이터 저장 (모든 객체가 공유해야 하는 값)
  • 객체 없이 접근해야 할 기능 (예: 유틸 메서드 Math.random())
  • 메모리 절약 (객체마다 따로 생성하지 않음)