static

기록하는 용도·2022년 8월 10일
0
post-thumbnail

Static

정적인 멤버, 클래스의 멤버를 정의할 때 사용한다.
별도의 객체 생성 없이 클래스로 접근해 사용한다.

컴파일 후 자바 프로그램 실행 단계는 아래와 같다.
1. 클래스 로딩 - 클래스 정보(임포트, 상속관계 등 붕어빵 틀 정보)와 함께 이 시점에 static member가 메모리(meta space) 영역에 미리 적재
2. 코드 검증 (Byte Code Verifier)
3. 실행을 하는 Runtime 실행 단계 - main이 실행되면서 -> 객체 생성 (heap 메모리 영역에 객체가 적재)

순서1에서 static variable (or class variable)은 class loading 시점에 meta space 메모리 영역 하나의 공간에 저장된다는것을 알 수 있다.
이와는 다르게 instance variable(object member variable)은 runtime시 객체 생성 후 heap 메모리 영역에 각각의 객체의 공간에 저장된다.

참고)

Java Memory는 다음과 같다.

Stack 영역 : local variable 정보가 저장되는 영역, LIFO (Last In, First Out)
Heap 영역 : Object의 instance variable 정 보가 저장되는 영역
Meta space 영역 : class의 meta data(package, class, method ...)가 저장되는 영역으로 static member 정보가 저장된다.



예제1)

package stpe1;

class StaticExam1{
	int bonus; // instance variable (object member variable)
	static int money; //static variable (class member variable)
	
	public void test1() { //method
		System.out.println("object member method");
	}
	
	public static void test2() { //static method
		System.out.println("class member method == static method");
	}
}

public class TestStatic1 {
	public static void main(String[] args) {
		StaticExam1 e = new StaticExam1();
		System.out.println(e.bonus); //bonus에 접근하는법
//		System.out.println(StaticExam1.bonus);
//		non-static이기때문에 반드시 객체를 생성해야한다.
		
		System.out.println(StaticExam1.money); 
		//static은 별도의 객체 생성없이 클래스이름.static멤버로 접근 가능
		
		StaticExam1.test2(); //static method 이므로 클래스, 메소드로 호출 가능
//		StaticExam1.test1(); 
//		compile error, non-static method이므로 객체생성이 반드시 필요하다.
		e.test1();
	}
}

첫줄부터 살펴보면서 static의 특징을 알아보도록하자.

int bonus; 

1.bonus 변수는 instance variable (object member variable)로 선언되었다. 위에 설명과 같이 자바 프로그램 순서3에서 실행을 하는 Runtime 실행 단계에 heap 메모리에 적재된다.


static int money; 

2.money 변수는 static variable (class member variable)로 선언되었다. static member이기 때문에 클래스 로딩시(순서1)에 meta space 메모리에 적재된다.


public void test1() { //method
	System.out.println("object member method");
}
	
public static void test2() { //static method
	System.out.println("class member method == static method");
}
  1. 인스턴스 메소드와 static (class) 메소드 두개가 선언되었다.



public static void main(String[] args) {
		StaticExam1 e = new StaticExam1();
		System.out.println(e.bonus); 
//		System.out.println(StaticExam1.bonus);
//		non-static이기때문에 반드시 객체를 생성해야한다.
		
		System.out.println(StaticExam1.money); 
		//static은 별도의 객체 생성없이 클래스이름.static멤버로 접근 가능
		
		StaticExam1.test2(); //static method 이므로 클래스, 메소드로 호출 가능
//		StaticExam1.test1(); 
//		compile error, non-static method이므로 객체생성이 반드시 필요하다.
		e.test1();
	}
  1. main 함수를 살펴보자.
StaticExam1 e = new StaticExam1();
System.out.println(e.bonus); 

e.bonus 코드를 통해 bonus 변수에 접근하고있다.
int는 0으로 초기화되기에 0을 출력할 것이다.


//		System.out.println(StaticExam1.bonus);

주석처리된 코드를 살펴보자.
bonus의 값을 알기위해 클래스이름.변수 로 접근하고있다.

여기서 주의할 점이 있다. 왜 우리는 위에 코드처럼 e.bonus 로 접근하는 것일까?
이또한 실행 순서와 관련이 있다.
앞서 말한것처럼 instance 변수는 런타임시 heap 메모리 영역에 객체가 생성된 후 적재된다.
무조건 객체를 생성해야만 접근할 수 있다는 것이다.
때문에 객체를 생성하지않는 StaticExam1.bonus 코드로는 결과값을 알 수 없다.


System.out.println(StaticExam1.money); 

static은 별도의 객체 생성없이 클래스이름.static멤버로 접근이 가능하다.


StaticExam1.test2(); 

test2()는 static member로 선언되었다.
클래스이름.메소드로 호출 가능하다.


e.test1();

e는 객체 생성된 참조 변수 이기때문에 instance method인 test1()을 객체를 생성하고 올바르게 호출한 것을 알 수 있다.




예제2)

static과 non-static과의 접근 특성

package stpe1;

class StaticExam2{
	int money1; //non-static, instance variable
	static int money2; //static variable
	
	public void test1() {
		// non static method 내부에서 접근 여부를 테스트
		System.out.println(money1); //같은 non-static이기때문에 접근 가능
		System.out.println(money2); //static은 미리 메모리에 적재됨으로 접근 가능한 것이다.
	}
	
	public static void test2() { //클래스 로디잇점에 저장되기때문에 메타스페이스에 non-static i.v new로 객체 생성할때 메모리에 있다 없다 보장할수 없기때문에 객체 생성하고 접근해야
		//
		// static method 내부에서 접근 여부 테스트
		System.out.println(money2); //같은 static 끼리이므로 접근 가능
//		System.out.println(money1);
//		static 에서 non-static으로 instance variable로 직접 접근은 불가
//		이유는 static은 객체 생성 없이 미리 클래스 로딩시에 메모리에 적재가되고 (meta space) ,
//		i.v인 money1은 객체 생성을 할때만 메모리에 (heap) 적재되므로 직접 접근 불가능하고 접근을 위해서는 객체 생성 작업이 선행되어야 한다.
		
//		아래와같이 객체 생성해서 접근하면 된다.
		StaticExam2 exam = new StaticExam2();
		System.out.println(exam.money1);
	}
}
public class TestStatic2 {
	public static void main(String[] args) {
		StaticExam2 exam = new StaticExam2(); 
		exam.test1();
		StaticExam2.test2(); //test2 메서드가 static 이므로 클래스로 접근해 객체 생성 없이 사용 가능
	}
}
int money1; //non-static, instance variable
static int money2; //static variable

money는 non-static으로 instance variable이다. 객체 생성 후 사용할 수 있다.
money2는 static variable로 만들어졌다. 런타임 이전에 클래스 로딩시 생성된다.



2.

public void test1() {
	System.out.println(money1); 
	System.out.println(money2); 
	}
	

non static method 내부에서 접근 여부를 테스트한다.
test1()은 non-static method이다.
money1은 같은 non-static이기때문에 접근이 가능하다.
money2는 static variable로 이의 특징은 미리 메모리에 적재됨으로 접근 가능한 것이다.
즉 test1()을 호출한다면 money2는 이전에 클래스 로딩시 메모리에 적재되어있기때문에 접근 가능하다.



3.

public static void test2() { 
		System.out.println(money2); //같은 static 끼리이므로 접근 가능
//		System.out.println(money1);
//		static 에서 non-static으로 instance variable로 직접 접근은 불가
//		이유는 static은 객체 생성 없이 미리 클래스 로딩시에 메모리에 적재가되고 (meta space),i.v인 money1은 객체 생성을 할때만 메모리에 (heap) 적재되므로 직접 접근 불가능하고 접근을 위해서는 객체 생성 작업이 선행되어야 한다.
		
//		아래와같이 객체 생성해서 접근하면 된다.
		StaticExam2 exam = new StaticExam2();
		System.out.println(exam.money1);
	}

static method 내부에서 접근 여부 테스트이다.
test2()는 static method로 만들어졌다.클래스 로딩시점에 저장되기때문에 meta space에 non-static i.v new로 객체를 생성하는 시점에 메모리에 있는지 없는지 보장할 수 없기때문에 여기서 접근하려면 객체를 생성하고 접근해야한다.

public static void main(String[] args) {
		StaticExam2 exam = new StaticExam2(); 
		exam.test1();
		StaticExam2.test2(); //test2 메서드가 static 이므로 클래스로 접근해 객체 생성 없이 사용 가능
	}

instance member인 test1()은 객체를 생성하고 접근하고, class member(static)인 test2()는 클래스로 접근해 객체 생성 없이 사용가능하다.

static과 non-static 접근
:static에서 non-static으로 접근하기 위해서는 반드시 객체 생성이 필요하다.
:non-static에서 static으로 접근은 바로 가능





예제3)

public class TestStatic7 {
	public static void main(String[] args) {
		System.out.println("main 실행");
	}
	static { 
		System.out.println("static 초기화 영역");
	}
	
}

static 초기화 영역
main 실행

static 초기화 영역은 메인 메소드에 우선해서 실행된다는 것을 알 수 있다.

0개의 댓글