Language`/Java

[Java] 변수의 선언위치

Avenus 2022. 2. 17. 20:26

변수

  변수 종류 선언 위치 생성시기
전역변수 클래스 변수
(static)
클래스 영역 클래스가 메모리에 올라갈 때
인스턴스 변수 인스턴스가 생성되었을 때
지역변수 클래스 이외의 영역
(메소드 / 생성자 / 초기화 블럭 내부)
변수 선언문이 수행되었을 때

 

클래스 변수 (static)

- static이 붙은 모든 변수

- 클래스내의 어디서든 사용이 가능하다 :: 공유가 자유롭다

- 인스턴스 없이 바로 사용할 수 있다 :: 클래스이름.클래스변수 

- 클래스가 메모리에 로딩될 때 생성되고, 프로그램 종료까지 유지된다

- 어디서 사용하든 해당 변수에 대해서는 전부 공통적인 값을 가지고 있다

- JVM내에 메소드 영역에 생성된다

>> 클래스 멤버(static)은 클래스 멤버만 호출 가능하다

 

인스턴스 변수

- 클래스의 인스턴스를 생성할 때 만들어진다

- 클래스 변수와 달리 각각의 변수는 독립적인 공간을 가진다

- JVM내에 힙 영역에 생성된다

>> 인스턴스 멤버는 인스턴스/클래스 멤버 둘다 호출 가능하다

 

지역변수

- 메소드 내에 선언되어서, 메소드 내에서만 사용이 가능하다

- 메소드가 종료되면 절대 사용할 수 없다

- JVM내에 스택 영역에 생성된다


변수의 초기화

- 지역변수는 반드시 초기화해야 한다

- 멤버변수(클래스/인스턴스 변수), 배열은 초기화가 선택적이다

  • 자동으로 해당 Type의 기본값으로 초기화된다
자료형 default 초기화값
boolean false
char '\u0000'
byte, short, int 0
long 0L
floag 0.0f
double 0.0d or 0.0
참조형 변수
(String, 배열,...)
null

 

명시적 초기화 (Explicit initialization)

- 변수의 선언과 동시에 초기화하는 방법

int door = 4; // 기본형 변수 초기화
Point p = new Point(); // 참조형 변수 초기화

 

인스턴스 초기화 블럭

- 인스턴스변수의 복잡한 초기화에 사용

  • 단순히 클래스내에 블럭{}을 만들고 그안에 초기화 코드를 작성하면 된다

- 생성자와 동일하게 인스턴스를 생성할 때 수행

  • 생성자보다 인스턴스 초기화 블럭이 먼저 수행된다

 

클래스 초기화 블럭

- 클래스변수의 복잡한 초기화에 사용

  • 인스턴스 초기화 블럭 앞에 static을 덧붙이면 된다

- 클래스가 처음 로딩될 때 한번만 수행 

class A{
    static {
    // 클래스 초기화 블럭
    }
    
    {
    // 인스턴스 초기화 블럭
    }
}

public class test3{

    static{
        System.out.println("static init {}");
    }

    {
        System.out.println("instance init {}");
    }

    test3(int n){
        System.out.println("생성자" + n);
    }


    public static void main(String[] args) {
        System.out.println("main() 내에 문장1");
        test3 t1 = new test3(1);

        System.out.println("main() 내에 문장2");
        test3 t2 = new test3(2);
    }
}
-----------------------------------------------
static init {} // 클래스 초기화 블럭내에 존재하는 문장
main() 내에 문장1 // main() 내에 존재하는 문장
instance init {} // 인스턴스 초기화 블럭내에 존재하는 문장
생성자1 // 클래스의 생성자
main() 내에 문장2 // main() 내에 존재하는 문장
instance init {} // 인스턴스 초기화 블럭내에 존재하는 문장
생성자2 // 클래스의 생성자
  • 클래스 초기화 블럭내에 존재하는 println문장은 main메소드 실행 후 한번만 수행된다
  • 인스턴스 초기화 블럭내에 존재하는 println문장은 인스턴스가 생성될때마다 수행된다

>> 결과를 보면 인스턴스 초기화 블럭은 생성자보다 먼저 수행된다는 것을 알 수 있다


멤버변수 초기화 시기/순서

  클래스 변수 인스턴스 변수
초기화 시점 클래스가 처음 로딩될 때 단 한번 초기화 인스턴스가 생성될 때마다 각 인스턴스별로 초기화
초기화 순서 1. 기본값
2. 명시적 초기화
3. 클래스 초기화 블럭
1. 기본값
2. 명시적 초기화
3. 인스턴스 초기화 블럭
4. 생성자
class A{
    static int v1 = 1;
    int v2 = 10;
    
    static{
        v1 = 2;
    }

    {
        v2 = 20;
    }
    
    A(){
        v1 = 3;
        v2 = 30;
    }
}​

1. 클래스 초기화

1. 기본값 2. 명시적 초기화 3. 클래스 초기화 블럭
v1 = 0 v1 = 1 v1 = 2

 

2. 인스턴스 초기화

1. 기본값 2. 명시적 초기화 3. 인스턴스 초기화 블럭 4. 생성자
클래스 변수 v1 = 2
v2 = 0 v2 = 10 v2 = 20 v2 = 30

>> 클래스 변수는 반드시 인스턴스변수보다 항상 먼저 생성되고 먼저 초기화된다