새소식

Java

[Java] 정적(static) 이란 무엇인가

  • -
728x90

알고리즘을 풀이하며 정적 변수, static 을 많이 사용하곤 한다. 이에 대한 정확한 의미에 대해 알아보고 분석해 보고자 글을 작성한다.

 

자바에서 static 키워드는 클래스 레벨의 변수나 메소드, 블록을 정의할 때 사용된다. 이는 인스턴스 생성 없이도 접근 가능하며, 모든 인스턴스에서 공유된다. static 변수는 프로그램이 시작할 때 메모리에 할당되고 프로그램이 종료될 때까지 유지된다.

왜냐하면 static 멤버는 클래스가 로드될 때 메모리의 메소드 영역에 할당되기 때문이다. 이는 모든 인스턴스가 공유하는 특성 때문에 유용하게 사용될 수 있다. 예를 들어, 어떤 클래스의 인스턴스들이 공통적으로 사용해야 하는 값을 static 변수로 선언할 수 있다.

하지만, static 키워드의 남용은 객체지향 프로그래밍의 원칙과 상반되며, 메모리 사용량 증가로 이어질 수 있습니다. 따라서 static 멤버의 사용은 신중하게 결정해야 한다.

왜냐하면 static 멤버는 프로그램 종료 시까지 메모리에 남아 있어, 과도한 static 사용은 메모리 누수의 원인이 될 수 있기 때문이다. 이는 특히 대규모 애플리케이션에서 성능 저하의 원인이 될 수 있다.

 

런타임 데이터 영역

 

static은 일반 인스턴스와는 다르게 static 영역에 메모리를 할당 하기 때문에 인스턴스 static 메서드에서는 아직 메모리가 할당 되지 않은 인스턴스 메서드를 사용 할 수 없다.

 

🔽 정적(Static) 멤버 생성

 

 

Static 키워드를 통해 생성된 정적 멤버들은 Heap 영역이 아닌 Static 영역에 할당된다. Static 영역에 할당된 메모리는 모든 객체가 공유하여 하나의 멤버를 어디서든지 참조할 수 있는 장점을 가지지만 Garbage Collector 의 관리 영역 밖에 존재하기에 Static 영역에 있는 멤버들은 프로그램의 종료시까지 메모리가 할당된 채로 존재하게 된다. 그렇기에 Static 을 너무 남발하게 되면 만들고자 하는 시스템 성능에 악영향을 줄 수 있다.

 

💡Static 영역과 Heap 영역

🔻Static 영역

Static 영역, 또는 Method 영역이라고 불리는 이 영역은 JVM 이 시작될 때 생성되고, 프로그램이 종료될 때 해제된다. 이 영역에는 다음과 같은 정보들이 저장된다.

 

클래스 정보

- 클래스의 메타데이터, 클래스에 대한 정보 (클래스 이름, 부모 클래스 등) 가 저장된다.

 

정적 변수

- 클래스에 선언된 `static` 키워드를 가진 변수들이 저장된다. 이 변수들은 클래스의 모든 인스턴스에서 공유되며, 클래스 로드 시 할당되고, 프로그램 종료 시 메모리에서 해제된다.

 

상수

- `final` 키워드와 함께 선언된 상수도 이 영역에 저장된다.

 

메서드 코드

- 클래스의 메서드 구현 코드가 저장되며,  이 코드는 모든 객체가 공유한다.

 

class Company {
    static String companyName = "OpenAI";

    static String getCompanyName() {
        return companyName;
    }
}

 

예를 들어, 다음과 같은 클래스에서 `companyName`과 `getCompanyName()` 메서드 구현이 Static 영역에 저장된다.

 

🔻Heap 영역

Heap 영역은 런타임에 동적으로 할당되는 데이터를 저장하는 영역으로, 객체와 배열이 저장된다. 모든 객체의 인스턴스와 배열은 힙에 생성된다. 이 영역은 가비지 컬렉터에 의해 관리되며,  더 이상 참조되지 않는 객체들은 가비지 컬렉터가 정리한다.

 

객체의 인스턴스 데이터

- 객체 각각의 상태 정보(인스턴스 변수)가 저장된다.

 

참조 변수

- 객체를 가리키는 참조 변수들 역시 이 영역에 저장된다.

 

class Employee {
    String name;
    int age;

    Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

Employee emp = new Employee("John Doe", 30);

 

이 예에서 `Employee` 객체 `emp` 는 힙 영역에 할당되며, `name`과 `age` 인스턴스 변수도 같은 영역에 저장된다.

 

Static 영역은 클래스 관련 데이터와 정적 변수를 저장하고, 이는 모든 인스턴스 간에 공유된다.
Heap 영역은 각 객체의 인스턴스 데이터를 동적으로 저장하며, 객체가 더 이상 필요하지 않을 때 가비지 컬렉터에 의해 정리된다.

 

🔽 정적(Static) 멤버 선언

필드나 메소드를 생성 시 인스턴스로 생성할것인지 정적으로 생성할것인지에 대한 판단 기준은 공용으로 사용하느냐 아니냐로 내리면 된다. 그냥 생성한다면 자동으로 인스턴스로 생성되며 정적으로 생성하려면 필드와 메소드 선언 시 static이라는 키워들를 추가적으로 붙이면 된다. 

static int num = 0; //타입 필드 = 초기값
public static void static_method(){} //static 리턴 타입 메소드 {}

 

🔽 정적(Static) 필드 사용 예시

class Number{
    static int num = 0; //클래스 필드
    int num2 = 0; //인스턴스 필드
}

public class Static_ex {
	
    public static void main(String[] args) {
    	Number number1 = new Number(); //첫번째 number
    	Number number2 = new Number(); //두번쨰 number
    	
    	number1.num++; //클래스 필드 num을 1증가시킴
    	number1.num2++; //인스턴스 필드 num을 1증가시킴
    	System.out.println(number2.num); //두번째 number의 클래스 필드 출력
    	System.out.println(number2.num2); //두번째 number의 인스턴스 필드 출력
    }
}

===============================================================================
1
0

 

Number이라는 클래스안에 클래스 변수 num과 인스턴스 변수 num2를 생성하였고 두개의 Number인스턴스 number1과 number2를 생성했을때 number1에서 num1과 num2를 각각 1씩 증가시키고 number2에서 num1와 num2를 각각 출력시켰을때는 num1은 1, num2는 0이 출력되었다.

 

왜 이런 현상이 나타났느냐면 인스턴스 변수는 인스턴스가 생성될 때마다 생성되므로 인스턴스마다 각기 다른 값을 가지지만 정적 변수는 모든 인스턴스가 하나의 저장공간을 공유하기에 항상 같은 값을 가지기에 나타난 현상이다.

 

🔽 정적(Static) 메서드 사용 예시

class Name{
    static void print() { //클래스 메소드
	System.out.println("내 이름은 홍길동입니다.");
    }

    void print2() { //인스턴스 메소드
	System.out.println("내 이름은 이순신입니다.");
    }
}

public class Static_ex {
	
    public static void main(String[] args) {
        Name.print(); //인스턴스를 생성하지 않아도 호출이 가능
    	
        Name name = new Name(); //인스턴스 생성
        name.print2(); //인스턴스를 생성하여야만 호출이 가능
    }
}

 

정적 메소드는 클래스가 메모리에 올라갈 때 정적 메소드가 자동적으로 생성된다. 그렇기에 정적 메소드는 인스턴스를 생성하지 않아도 호출을 할 수 있다. 정적 메소드는 유틸리티 함수를 만드는데 유용하게 사용된다.

 

참조 

https://coding-factory.tistory.com/524

https://f-lab.kr/insight/understanding-static-keyword-in-java?gad_source=1&gclid=Cj0KCQjwir2xBhC_ARIsAMTXk85okO6_hl1GF-HsPd0UgQixY3pFnrZ-mGTl9zQbopSUDzmr6bwC9pwaAlvzEALw_wcB

728x90
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.