JAVA

[자바] static 변수와 메서드

감자b 2024. 12. 24. 18:30

자바에서 static 키워드를 선언하면 메서드 영역에서 특별하게 관리된다. 이는 프로그램 실행에 생성되고 JVM이 종료될 때 까지 유지가 되어 (메서드 영역에 존재하므로 GC에 의해 제거되지 않음) 정적임을 뜻한다.

static 변수

클래스 변수, 정적 변수, static 변수 : static이 붙은 멤버 변수로 자바 프로그램이 시작될 때 초기화되며 메서드 영역에 딱 1개 생성. 인스턴스와 무관하며 여러 곳에서 공유하는 목적으로 사용된다.

↔ 인스턴스 변수 : static이 붙지 않은 멤버 변수로 인스턴스를 생성해야 사용 가능하며(동적) 생성된 인스턴스에 소속. (힙 영역)


static 메소드

변수와 마찬가지로 메서드에 static 키워드가 붙으면 정적 메서드 또는 클래스 메서드라고 한다.

↔ 인스턴스 메서드 : static이 붙지 않은 메서드로 인스턴스를 생성해야 호출이 가능한 메서드

  • static 메서드 사용 방법
    • static 메서드 내부에서는 static이 붙은 메서드나 변수만 접근이 가능하다.
    • static 메서드나 변수에 대해서는 모든 곳에서 접근이 가능하다. (접근제어자에 따라 다름)
public class Test {
    private int value = 0;
    private static int staticValue = 0;

    public void add() {
        addStatic();
        value++;
        staticValue++;
        System.out.println("value = " + value);
        System.out.println("staticValue = " + staticValue);
    }

    public static void addStatic() {
//        add(); 불가능
//        value++; 불가능
        staticValue++;
        System.out.println("staticValue = " + staticValue);
    }
}
public class TestMain {
    public static void main(String[] args) {
        Test test = new Test();
        test.add();
    }
}

출력 결과:

staticValue = 1 value = 1 staticValue = 2

 

  1. 프로그램이 실행되면 클래스 정보나 static 변수, 메서드는 메서드 영역에 올라간다.
  2. 메인 메서드가 실행되면 스택 영역에 메인 프레임이 올라간다.
  3. 메인 메서드에서 Test의 인스턴스인 test 가 생성되고 힙 영역에 올라간다.
  4. add() 메서드가 실행되고 스택 프레임이 스택 영역에 생성된다.
  5. add() 내부에서 addStatic() 메서드가 실행되고 마찬가지로 스택 영역에 올라간다.
  6. addStatic() 메서드에서 메서드 영역에 있는 staticValue의 값을 증가시키고 출력 후 종료되며 스택프레임에서 사라진다.
  7. add()에서 힙 영역에 있는 인스턴스 변수의 값과 메서드 영역에 있는 static 변수 값을 증가시킨 후 출력하고 스택프레임에서 제거된다.
  8. 메인 메서드가 종료되며 스택 영역이 비게 되어 프로그램이 종료된다.

위 코드에서 static 메서드에서 인스턴스 변수나 메서드에 접근할 수 없는 이유는 무엇일까?

힙 영역에 있는 test는 new 연산이 있을 때 생성된다. 하지만 static은 앞서 말했다시피 프로그램 실행과 동시에 메서드 영역에 만들어지고 객체의 생성이 필요없이 접근이 가능한데 여기서 정적 메서드는 만들어진 인스턴스의 참조값을 알 수 없고 메모리가 할당도 되기 전이기 때문에 접근이 불가능하다.

 

위 코드에서 정적 메서드는 Test.addStatic()처럼 객체 생성없이 접근이 가능하다.

이처럼 정적 메서드는 주로 간단한 메서드 하나로 끝나는 유틸리티성 메서드에 자주 사용된다.(java.lang Math 클래스)


private static method를 쓰는 이유?

static 메서드는 공용으로 사용되는 메서드인데 이러한 static 메서드에 private을 사용하는 이유는 무엇일까?

private은 특정 기능을 캡슐화하고, 클래스의 내부 구현을 보호하는 데 유용하다.

그리고 static 메서드는 주로 인스턴스 생성이 필요없는 유틸리티성 메서드를 작성하는데 주로 사용된다.

public인 유틸리티성 메서드를 작성할 때 내부에서 코드 중복 제거 등의 목적으로 클래스 내부에서만 사용할 용도로 작성하기 위해 private 메서드를 만드는데 static 메서드는 static만 호출이 가능하므로 이런 경우에 private static method를 만들기도 한다.

public class Collections {
	......
	public static void shuffle(List<?> list, RandomGenerator rnd) {
		int size = list.size();
		if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
			for (int i=size; i>1; i--) swap(list, i-1, rnd.nextInt(i));
		} else {
			Object[] arr = list.toArray();

			// Shuffle array
			for (int i=size; i>1; i--) swap(arr, i-1, rnd.nextInt(i));   //<--- private static method

			// Dump array back into list
			// instead of using a raw type here, it's possible to capture
			// the wildcard but it will require a call to a supplementary
			// private method
			ListIterator it = list.listIterator();
			for (Object e : arr) {
				it.next();
				it.set(e);
			}
		}
	}
	private static void swap(Object[] arr, int i, int j) {
		Object tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}
	......
}