[Java] 객체지향 프로그래밍(oop) - 변수의 초기화

SolChan Kim·2023년 11월 30일
post-thumbnail

📖변수의 초기화

  • 변수를 선언하고 처음으로 값을 저장하는 것

  • 멤버변수(인스턴스 변수, 클래스 변수)와 배열은 각 타입의 기본값이므로
    자동초기화되므로 초기화를 생략할 수 있다.

    • 클래스 변수와 new연산자를 통해 생성되는 인스턴스, 배열은
      각 타입의 기본값으로 자동초기화 된다.
  • 지역변수는 사용전에 반드시 초기화를 진행해야 한다.

    • 지역변수는 자동초기화가 되지 않으므로 초기화가 꼭 필요하다.
public class InitTest{
	// 인스턴스 변수 : 초기화를 진행하지 않으면 기본값으로 자동 초기화
	int x;
    int y;
    
    public void method(){
    	int i;
        // 컴파일 에러 : 지역변수(i)를 초기화 없이 사용했기 때문 
        System.out.println(i);
    }
}

변수의 초기화 예시

// int형 변수 i를 선언하고 10으로 초기화
int i = 10;

// int형 변수 j를 선언하고 20으로 초기화
int j = 20;

// 같은 타입의 변수는 콤마(,)를 사용해 선언하거나 초기화 가능
int i = 10, j = 20;

// 타입이 다른 변수는 함께 선언하거나 초기화 불가능
int i = 10, long j = 20;

// 변수 i에 저장된 값으로 변수 j를 초가화 할 수 있다.
// 변수j는 i의 값인 10으로 초기화된다.
int i = 10;
int j = i;

// 변수 i가 선언되기 전에 i를 사용할 수 없다.
int j = i;
int i = 10;

📖멤버변수의 초기화

멤버변수(인스턴스 변수, 클래스 변수)는 변수가 만들어진 후에
바로 사용할 수 있는 상태가 되야 하기 때문에
변수의 생성과 동시에 적절한 초기화작업을 진행해야 한다.

멤버변수의 초기화 방법

명시적 초기화(explicit initialization)

  • 변수의 선언과 동시에 초기화를 진행하는 것
public class Car{
	// 기본형(primitive type) 변수의 초기화
	int doorNumber = 4;
    
    // 참조형(reference type) 변수의 초기화
    Engine engine = new Engine();
}

생성자(constructor)사용

public class Car{
	String carName, color;
    int doorNumber;
    
    // 생성자는 생성된 인스턴스의 멤버변수들을 초기화 하는데 사용된다.
    public Car(String carName, String color, int doorNumber){
    	this.carName = carName;
        this.color = color;
        this.doorNumber = doorNumber;
    }
    
}

초기화 블럭(initialization block)

  • 인스턴스 초기화 블럭 : {}

  • 클래스 초기화 블럭 : static{}


📖초기화 블럭(initialization block)

public class InitBlock{
	// 클래스 초기화 블럭
	static{ /*인스턴스 초기화 코드 */}
    
    // 인스턴스 초기화 블럭
    {/* 인스턴스 초기화 코드*/}
}
  • 초기화 블럭은 명시적 초기화만으로 처리할 수 없는 복잡한 초기화에 사용
  • 초기화 블럭은 내부적으로는 메서드로 처리된다.
    • 자동적으로 호출되는 초기화 메서드(생성자 = 메서드)
    • 초기화 블럭이 선언되는 영역 : 클래스 영역

클래스 초기화 블럭

  • 클래스 변수의 복잡한 초기화에 사용되며 클래스가 로딩될 때 실행된다.

  • 클래스 로딩 -> 클래스 변수 생성 -> 클래스 초기화 블럭 자동 호출
    -> 클래스 변수 초기화 수행

  • 클래스 초기화 블럭은 클래스가 로딩될 때 단 한번만 실행

  • 사용 방법 : static{}


인스턴스 초기화 블럭

  • 생성자에서 공통적으로 수행되는 작업에 사용되며,
    인스턴스가 생성될 때마다(생성자보다 먼저) 실행된다.

  • 인스턴스변수의 복잡한 초기화는 생성자를 이용하면 되므로 거의 사용X

  • 사용 방법 : 블럭{}을 만들고 인스턴스 초기화 코드 작성

public class StaticBlock{
	// 명시적 초기화 : 변수의 선언 및 초기화 진행
	static int[] intArr = new int[5];
    
    // 클래스 초기화 블럭 : static{}
    // 배열 intArr을 1~5순서대로 값을 저장한다.
    static{
    	for(int i = 0; i<intArr.length; i++){
        	intArr[i] = 1++;
        }
    }
}

📖멤버변수의 초기화 시기와 순서

멤버변수 초기화 순서

  • 명시적 초기화 > 초기화 블럭 > 생성자

  • 클래스 변수가 인스턴스 변수보다 먼저 초기화된다.


멤버변수의 초기화 시점

  • 클래스 변수의 초기화 시점 : 클래스가 처음 로딩될 때 단 한번

  • 인스턴스 초기화 시점 : 인스턴스가 생성될 때마다


자세히 살펴보기

1. InitTest클래스가 메모리에 로드되고,

InitTest클래스의 main메서드가 호출되면서 프로그램이 시작된다.

InitTest클래스가 메모리에 로딩될 때 정의된 클래스 변수 cv가 자동생성된다.

클래스변수cv는 명시적 초기화에 의해서 1로 초기화되어있다.


2. InitTest클래스 메모리에 로딩될 때, 클래스 초기화 블럭이 수행되어 클래스변수cv에 값 2를 저장한다.

  • 클래스 초기화 블럭이 종료되면 호출스택(Call Stack)에서 제거되고,
    클래스 초기화 블럭이 사용했던 메모리공간은 자동반환된다.
    그리고 클래스초기화 블럭이 수행되기 전 실행되었던 main메서드로 돌아간다.


3. InitTest타입의 참조변수 init가 main메서드의 지역변수로 선언된다.

new에 의해서 InitTest클래스의 인스턴스가 생성되고,

인스턴스의 인스턴스 변수 iv는 명시적 초기화에 의해서 1로 초기화된다.

생성된 인스턴스의 메모리주소는 참조변수 init이 참조하게 된다.

  • 🤔참조변수 init이 지역변수?
    • main메서드 안에서 참조변수 init가 선언되었기 때문에 지역변수다.


4. 인스턴스가 생성되면 인스턴스초기화 블럭이 수행된다.

따라서 인스턴스 변수 iv의 값을 2로 변경한다.

  • 인스턴스 초기화 블럭이 수행된 이후의 과정은
    클래스 초기화 블럭이 수행된 이후의 과정과 같다.

  • 🤔인스턴스를 생성하면 생성자가 먼저 호출되는게 아닌가?

    • 인스턴스 초기화 블럭은 인스턴스를 생성할 때마다 가장 먼저 호출된다.


5. 생성자가 호출되어 인스턴스 초기화 작업을 진행한다.

인스턴스 변수 iv의 값이 2에서 3으로 변경된다.

업로드중..


6. main메서드에 남아있는 println메서들을 호출한다.

    1. print()메서드 호출
    • 호출결과 : cv : 2
    • 호출스택에서 제거, main메서드로 돌아감
    1. println()메서드 호출
    • 호출결과 : iv : 3
    • 호출스택에서 제거, main메서드로 돌아감
    1. main메서드에 더이상 수행할 문장이 없음
    • 호출스택에서 main메서드 제거, 프로그램 종료

0개의 댓글