반응형
1. static 이란?
static 이란 '정적인', '고정적인' 이라는 사전적 의미를 가진다. 이를 java 관점으로 해석하면 '클래스의' 또는 '공통적인' 이라는 의미를 가진다. static 을 이해하기 위해서는 먼저 JVM (자바 가상 머신) 을 이해할 필요가 있다.
◼︎ JVM ( Java Virtual Machine, 자바 가상 머신 )
쉽게 말하면 '자바를 실행하기 위한 가상의 컴퓨터' 라고 할 수 있다.
- java 애플리케이션을 실행하면 JVM 은 OS 로부터 메모리를 할당한다.
- 자바 컴파일러 (javac) 가 자바 소스코드 (Xxx.java) 를 바이트코드 (Xxx.class) 로 컴파일 한다.
- 클래스 로더 (Class Loader) 를 통해 JVM 메모리 (Runtime Data Areas) 로 로딩한다.
- 로드된 클래스 파일 (Xxx.class) 들은 기계가 읽을 수 없으므로 실행 엔진 (Execution Engine) 을 통해 기계어로 변환하여 실행한다.
- 이 과정에서 실행엔진에 의해 가비지 콜렉터 (Garbage Collector) 등도 작동된다.
자바 어플리케이션이 실행되면 JVM은 시스템으로부터 필요한 메모리를 할당받고, 용도에따라 여러 영역으로 나누어 관리한다. Method Area, Call Stack, Heap 이 대표적이다.
- 메소드 영역 (Method Area)
- JVM 이 클래스 파일 (*.class) 을 읽어 클래스 데이터를 저장하는 영역이다. 이때 클래스 변수도 함께 생성된다.
- 힙 (Heap)
- 인스턴스가 생성되는 공간이다. 프로그램 실행 중 new 연산으로 생성되는 인스턴스 변수들이 생성된다.
- 호출 스택 (Call Stack)
- 메소드의 작업에 필요한 메모리 공간을 제공한다. 메소드가 호출되면 호출 스택에 메모리가 할당되고 해당 메소드가 수행되는 동안 필요한 값 등을 저장하는데 사용된다. 메소드 실행이 완료되면 할당되었던 메모리 공간은 반환된다.
2. static 변수
- 클래스 변수
- 한 클래스에서 공통적인 값을 유지해야할때 선언한다.
- 클래스가 메모리에 로딩될 때 생성되어 프로그램이 종료될 때 까지 유지된다.
- 객체를 생성하지 않고도 '클래스이름.변수명' 으로 호출이 가능하다.
// static 변수 (클래스 변수)
public class MyMathStaticBasic {
public static final String DESCRIPTION = "static 변수";
}
// 인스턴스 변수
public class MyMathBasic {
public long a;
public long b;
public String description = "인스턴스 변수";
}
• 테스트
@Test
@DisplayName("static 변수, 인스턴스 변수")
public void staticStr() {
//static 변수는 인스턴스를 생성하지 않아도 사용할 수 있다.
System.out.println("static 변수 출력 = " + MyMathStaticBasic.DESCRIPTION);
//인스턴스 변수는 인스턴스를 생성해야 사용할 수 있다.
MyMathBasic mathBasic = new MyMathBasic();
System.out.println("인스턴스 변수 출력 = " + mathBasic.description);
}
• 결과
static 변수 출력 = static 변수
인스턴스 변수 출력 = 인스턴스 변수
3. static 메소드
- 클래스 메소드
- 인스턴스 변수를 사용할 수 없으므로 인스턴스와 관계없는 메소드를 클래스 메소드 (static 메소드) 로 정의한다.
- 객체를 생성하지 않고도 '클래스이름.메소드명' 으로 호출이 가능하다.
// static 변수, static 메소드 (클래스 변수, 클래스 메소드)
public class MyMathStaticBasic {
public static final String DESCRIPTION = "static 변수";
/** 매개변수로 가능 */
public static long add(long a, long b) { return a + b; }
public static long subtract(long a, long b) { return a - b; }
public static long multiply(long a, long b) { return a * b; }
public static double divide(long a, long b) { return a / b; }
}
// 인스턴스 변수
public class MyMathBasic {
long a;
long b;
String description = "인스턴스 변수";
/** 인스턴스 변수 a, b 만 이용하므로 매개변수가 필요없다. */
public long add() { return a + b; }
public long subtract() { return a - b; }
public long multiply() { return a * b; }
public double divide() { return a / b; }
}
• 테스트
@Test
@DisplayName("static 메소드")
public void mathStatic() {
long num1 = 100L;
long num2 = 10L;
System.out.println("add(num1, num2) = " + MyMathStaticBasic.add(num1, num2));
System.out.println("subtract(num1, num2) = " + MyMathStaticBasic.subtract(num1, num2));
System.out.println("multiply(num1, num2) = " + MyMathStaticBasic.multiply(num1, num2));
System.out.println("divide(num1, num2) = " + MyMathStaticBasic.divide(num1, num2));
assertEquals(110L, MyMathStaticBasic.add(num1, num2));
assertEquals(90L, MyMathStaticBasic.subtract(num1, num2));
assertEquals(1000L, MyMathStaticBasic.multiply(num1, num2));
assertEquals(10.0, MyMathStaticBasic.divide(num1, num2));
}
@Test
@DisplayName("인스턴스 메소드")
public void mathBasic() {
MyMathBasic mathBasic = new MyMathBasic();
mathBasic.a = 200L;
mathBasic.b = 10L;
System.out.println("add() = " + mathBasic.add());
System.out.println("subtract() = " + mathBasic.subtract());
System.out.println("multiply() = " + mathBasic.multiply());
System.out.println("divide() = " + mathBasic.divide());
assertEquals(210L, mathBasic.add());
assertEquals(190L, mathBasic.subtract());
assertEquals(2000L, mathBasic.multiply());
assertEquals(20.0, mathBasic.divide());
}
• 결과 (static 메소드)
add(num1, num2) = 110
subtract(num1, num2) = 90
multiply(num1, num2) = 1000
divide(num1, num2) = 10.0
• 결과 (인스턴스 메소드)
add() = 210
subtract() = 190
multiply() = 2000
divide() = 20.0
4. 정리
- 클래스를 설계할 때, 멤버 변수 중 모든 인스턴스에 공통으로 사용하는 것에 static 을 선언한다.
- 클래스 변수 (static 변수) 는 인스턴스를 생성하지 않아도 호출할 수 있다.
- 클래스 메소드 (static 메소드) 는 인스턴스 변수를 사용할 수 없다.
- 메소드 내에서 인스턴스 변수를 사용하지 않는다면, static 을 붙이는 것을 고려하자.
- 클래스의 멤버변수 중 모든 인스턴스에 공통된 값을 유지해야하는 것이 있다면 static 을 선언한다.
- 작성한 메소드 중에 인스턴스 변수나 인스턴스 메소드를 사용하지 않는 메소드에는 static 을 선언할 것을 고려한다.
반응형