본문 바로가기

Java/문법

9-2장 static 제어자

- static 

 - 클래스의 멤버(필드, 메서드, 이너 클래스)에 사용하는 제어자 

 

- 인스턴스 멤버(instance member)

 - 객체 안에 있을 때 상요할 수 있는 상태가 되는 멤버 

 

- 정적 멤버(static member)

 - static이 붙어 있는 멤버 

 - 객체의 생성 없이 '클래스명.멤버명'만으로 바로 사용 가능

 

1. 인스턴스 필드와 정적 필드 

 

class A {
	int m = 3; //객체를 생성한 후 사용 가능
    static int n =5; //객체 생성 없이 사용 가능
}

- 인스턴스 필드와 정적 필드의 메모리 구조 

- 인스턴스 필드의 활용 방법 - 객체를 생성한 후에 사용 가능

A a = new A();
System.out.println(a.m); //3

 - '참조 변수명. 인스턴스 필드명'

 - 인스턴스 필드인 m의 저장공간은 객체 내부에 생성되므로 m을 사용하기 위해서는 반드시 객체를 먼저 생성

 - 저장공간이 힙 메모리에 위치하므로 반드시 해당 저장 공간에 값을 읽거나 쓰기 위해서는 참조 변수명 사용

 

- static 필드의 활용 방법 1 - 객체를 생성하지 않고 바로 사용

System.out.println(A.n); //5

 - '클래스명.정적 필드명'

 - 정적 필드인 n은 클래스 내부에 저장 공간을 지니고 있기 떄문에 객체 생성 없이 바로 사용 가능

 

- static 필드의 활용 방법 2 - 객체를 생성한 후 사용(권장 x)

A a = new A();
System.out.println(a.n); //5

 - 객체 내부에 정적 필드인 n도 존재

 - n의 실제 저장 공간 = 정적(static)영역 

   n의 저장공간의 참좃값 = 객체 내부 영역

 - 인스턴스 필드 처럼 참조 변수명으로도 사용 가능

 

- 정적필드는 객체 간 공유 변수의 성질이 있다.

 

- 정적 필드의 공유 특성 예

A a1 = new A();
A a2 = new A();

a1.m =5; //a1 객체의 인스턴스 필드 m에 값 5 입력
a2.m =6; //a1 객체의 인스턴스 필드 m에 값 6 입력
System.out.println(a1.m); //5
System.out.println(a2.m); //6

a1.n = 7; //a1 객체의 정적 필드 n에 값 7 입력
a2.n = 8; //a1 객체의 정적 필드 n에 값 8 입력
System.out.println(a1.n); //8
System.out.println(a2.n); //8

A.n = 9;
System.out.println(a1.n); //9
System.out.println(a2.n); //9

 

- 객체 a1, a2를 생성하면 힙 메모리에 2개의 객체가 만들어짐

- 인스턴스 필드 m은 객체안에 실제 데이터 값 저장

- 정적 필드 n은 정적(클래스)영역의 클래스 A안에 실제데이터값 저장

  객체 안에는 실제데이터값의 위칫값을 저장

- a1 객체의 정적 필드 n과 a2 객체의 정적 필드 n은 모두 클래스 A에 저장된 값을 똑같이 가리키고 있음

  -a1.n = 7 입력시 n이 가리키는 곳에 7을 저장

  -a2.n = 8 입력시 n이 가리키는 곳에 8dmf wjwkd

  -두 정적 필드 n이 가리키는 곳이 같으므로 기존에 저장돼 있던 값 7이 지워지고 8이 저장

 

- 정적필드가 사용되는 예

 - 은행통장 클래스로 열 사람의 은행통장 객체를 생성

 - 이자필드 = 정적 필드 

 - 금리가 바뀌어 '은행통장.클래스.이자'를 바꾸면 모든 은행통장 객체들이 모두 이 값을 적용받게 됨

 

2. 인스턴스 메서드와 정적 메서드 

 

 - 인스턴스 메서드  : 반드시 객체를 생성한 후에 사용

 - 정적 메서드 : 클래스명으로 바로 접근 가능

class A {
	void abc() {
    	System.out.println("instance 메서드");
    }
    static void bcd() {
    	System.out.println("static 메서드");
    }
}

//인스턴스 메서드의 활용 방법
A a = new A(); //객체를 생성한 후에 사용 가능
a.abc(); 

//정적 메서드의 활용 방법
A.bcd();

 - 인스턴스 메서드와 정적 메서드는 모두 메모리의 첫 번째 영역에 위치 

 - 인스턴스 메서드는 인스턴스 메서드 영역, 정적 메서드는 클래스 내부에 존재

 - 인스턴스 메서드와 정적 메서드의 메모리 구조

 

3. 정적 메서드 안에서 사용할 수 있는 필드와 메서드 

 

- 정적 메서드 내에서는 정적 필드 또는 정적 메서드만 사용 가능

- 인스턴스 메서드 내에서는 인스턴스 멤버와 정적 멤버 모두 사용 가능

- 정적 멤버 ( 정적 필드, 정적 메서드)는 객체의 생성 없이 실행될 수 있어야 함

- But, 인스턴스 멤버(인스턴스 필드, 인스턴스 메서드)는 반드시 객체를 생성한 후에 사용 가능

- 객체 생성 이전에 실행하려면 내부에는 객체 생성 이전에 사용할 수 있는 요소들로만 구성돼 있어야 함

 

- 정적 메서드 내부에서는 클래스 내부에서 자신의 객체를 가리키는 this 키워드를 사용할 수 없음

- this.가 자동으로 붙어야 하는 인스턴스 멤버는 올 수 없음

 

class A {
	int a;
    static int b;
    void abc() {
    	//a,b, bcd(), cde() 사용 가능 
    }
    static void bcd() {
     	//b,cde() 사용 가능
    }
    static void cde() {
    	//b, bcd() 사용 가능
    }
}

 

4. 정적 초기화 블록

 

- 인스턴스 필드의 초기화는 객체가 만들어지는 시점에서 이뤄짐. 즉, 객체가 생성자에서 만들어지므로 생성자 내에서 인스턴스 필드를 초기화

- 정적 필드는  객체의 생성 이전에도 사용할 수 있어야 하므로 생성자가 호출되지 않은 상태에서도 초기화할 수 있어야 함 

- 생성자에서는 정적 필드를 초기화 할 수 없음

- 정적 초기화 블록(static {})사용

static {
	//클래스가 메모리에 로딩될 떄 실행되는 내용
}

 - 정적 초기화 블록은 클래스가 메모리에 로딩될 때 가장 먼저 실행

 - 여기에 정적 필드의 초기화 코드를 넣어 두면 클래스가 로딩되는 시점에 바로 추가 

package StaticInitialBlock;

class A {
	int a;
	static int b;
	static {
		b=5; //정적 필드의 초기화는 static{}내에서 수행
		System.out.println("클래스 A가 로딩됐습니다!");
	}
	A() {
		a=3; //인스턴스 필드 초기화는 일반적으로 생성자에서 수행
	}
}
public class StaticInitialBlock {
	public static void main(String[] args) {
		System.out.println(A.b); //A.b가 실행되는 시점에 클래스 A가 메모리에 로딩되며, 이때 static{} 초기화 블록 실행
	}
}

 

5. static main() 메서드 

 

- public static void main(String[] ar)도 정적 메서드 

- 자바 가상 머신은 프로그램을 실행할 때 '실행 클래스명.main()'을 실행하므로 가장 먼저 실행되는 메서드인 main()메서드를 정적 메서드로 구현

'Java > 문법' 카테고리의 다른 글

10-2장 객체의 타입 변환  (0) 2023.05.04
10-1장 클래스 상속의 개념과 문법적 특징  (0) 2023.05.04
9-1장 접근 지정자  (0) 2023.04.30
8-2 장 외부 클래스  (0) 2023.04.24
8-1장 패키지와 임포트  (0) 2023.04.24