Java

[Java] static의 의미와 사용법

자바바 2023. 9. 1. 16:49

정적(Static)이란?

static이란 "고정된"이란 의미를 갖고 있다. 객체를 생성하지 않고도 변수나 함수를 사용할 수 있다. static이라는 키워드로 정적 필드와 정적 메소드를 만들 수 있는데, 이 둘을 합쳐 정적 멤버(클래스 멤버)라고 한다. 정적 멤버는 객체(인스턴스)에 속한 멤버가 아니라 클래스에 고정된 멤버다.

 

그렇기에 클래스 로더가 클래스를 로딩해서 메소드 메모리 영역에 적재할 때, 클래스 별로 관리된다. 따라서 클래스 로딩이 끝나는 즉시 바로 사용할 수 있다.

 

 

정적(Static) 멤버 생성

 

static 키워드를 통해 생성된 정적 멤버들은  프로그램이 시작되면 Heap 영역이 아니라 Static 영역에 할당된다.

static 영역에 할당된 메모리는 모든 객체가 공유하여 하나의 멤버를 어디서든 참조할 수 있는 장점을 가진다.

하지만 Garbage Collector 관리 밖에 존재하기 때문에, static 영역에 있는 멤버들은 프로그램 종료시까지 메모리가 할당된 채로 존재하게 된다.

그렇기 때문에 static을 너무 남발하면 시스템 성능에 악영향을 줄 수 있다.

 

정적(Static) 멤버 선언

인스턴스로 생성할지 정적으로 생성할지 판단 기준은 공용으로 샤용하냐 아니냐로 내리면 된다.

// static 필드
static int 필드명 = 0;

// static 메소드
public static void 메소드명() { ... };

 

정적(Static) 필드 예시

class Number{
    static int static_num = 0; // static 필드
    int instance_num = 0; // 인스턴스 필드
}

public class Static_ex {
	
    public static void main(String[] args) {
    	Number n1 = new Number(); 
    	Number n2 = new Number();
    	
    	n1.static_num++; // static 필드 num을 1증가시킴
    	n1.instance_num++; // 인스턴스 필드 num을 1증가시킴
        
    	System.out.println(n2.static_num); 
    	System.out.println(n2.instance_num);
    }
}

실행 결과

1

0

 

왜 이런 결과가 나오냐?

인스턴스 변수는 인스턴스가 생성될 때마다 생성되므로, 각기 다른 값을 가진다.

하지만 정적 변수는 모든 인스턴스가 하나의 저장 공간을 공유해서 항상 같은 값을 가지기 때문이다.

 

객체마다 가지고 있어야 할 데이터  -> 인스턴스 필드
객체마다 가지고 있을 필요 없고, 공용 데이터  -> 정적 필드

 

정적(Static) 메소드 예시

class Name{
    static void print() { // static 메소드
		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(); // 인스턴스를 생성하여야만 호출이 가능
    }
}

실행 결과

내 이름은 홍길동입니다.

내 이름은 이순신입니다.

 

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

 

💡 Static은 언제 사용할까?

static은 메모리 문제(프로그램 종료 시점까지 메모리에서 해제되지 않는)와 테스트하기 어려움(전역으로 관리되기 때문에 프로그램 전체에서 필드에 접근하고 수정해서 해당 필드를 추론하기 어려움) 등의 문제가 있지만, 사용하면 좋은 상황들이 몇몇 있다.

상수 정의

절대 변하지 않는 변수를 상수라고 하는데, 상수는 객체 내에서 매번 일반 변수로 정의하기 보다는 한번 정적 변수로 정의하면 메모리를 아낄 수 있다.

private static final 리턴타입 필드명 [= "초기값";]

유틸리티 클래스

데이터 처리를 위한 정적 메소드만 존재하는 클래스. 애초에 객체의 상태를 이용할 생각이 없고, 여러 객체들의 필요에 의해 데이터를 처리하는 공통 로직이 필요할 때 사용한다.

 

 

인스턴스 메소드 vs 정적 메소드

static 메소드에서는 인스턴스 필드/메소드를 사용할 수 없다. ->  메모리에 생성되는 시점이 다르기 때문

 

static 메소드는 인스턴스가 없어도 사용 가능하지만, 인스턴스 필드는 인스턴스 생성이 있어야만 사용 가능하다.

static 메소드가 실행되는 시점에서는, 인스턴스 필드가 메모리에 있지 않으니까 사용할 수 없다고 컴파일 에러

객체 자신의 참조인 this 사용 불가

 


참조

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