09009

[Java] 클래스변수, 인스턴스변수, 초기화 블럭 본문

Back-End/JAVA
[Java] 클래스변수, 인스턴스변수, 초기화 블럭
09009

인스턴스변수

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

• 각 인스턴스는 독립적인 저장공간을 소유하고 서로 다른 값을 가질 수 있다

• 인스턴스마다 고유한 상태를 유지해야 하는 경우, 인스턴스 변수로 선언한다

 

클래스변수

 선언 방법: 인스턴스변수 앞에 static 작성

 클래스변수는 모든 인스턴스가 공통된 저장공간을 공유함

 한 클래스의 모든 인스턴스들이 공통적인 값을 유지해야 하는 경우, 클래스변수로 선언한다.

 인스턴스 변수와 달리 인스턴스를 생성하지 않고 바로 사용 가능 ('클래스이름.클래스변수'와 같은 형식으로 사용)

  클래스가 메모리에 로딩될때 생성, 프로그램이 종료될 때까지 유지

 

 

static

 static은 메서드 영역에 생성된다. 

 프로그램이 시작되는 시점에 생성된다. (딱 1개)

 static은 소멸이 되지 않는다.

static은 접근할 때 인스턴스를 생성하지 않고도 바로 접근이 가능하다. (클래스명.기본변수명)

 static은 어디서든 호출이 가능하다.

 static은 this를 사용할 수 없다.

class Card {
    String kind; // 인스턴스변수
    int number; // 인스턴스변수
    
     static int width = 100; // 클래스변수
     static int height = 250; // 클래스변수
}

인스턴스변수 : 인스턴스가 생성될 때마다 생성되므로 인스턴스마다 각기 다른 값 유지 가능

클래스변수: 모든 인스턴스가 하나의 저장공간을 공유하여 항상 공통된 값을 가짐

 

!! 인스턴스마다 개별적인 값을 가져야하는 변수는 인스턴스변수로 선언하고,

모든 인스턴스가 공통적인 값을 가져야하는 변수는 클래스 변수로 선언해야한다. !!


 

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

인스턴스변수의 초기화 시점: 인스턴스가 생성될 때마다 각 인스턴스별로 초기화 수행

 

 

입력

class Static2 {
    int x;
    static int y;
    void add() {
        x++;
        y++;
    }
}

public class Static2Ex {
    public static void main(String[] args) {
        for(int i = 0; i < 10; i++) {
            Static2 st = new Static2();
            st.add();
            System.out.println("x = " + st.x + ", y = " + st.y);
        }

    }
}

위의 소스코드에서 Static2 클래스에 선언된 x는 인스턴스변수이고, y는 클래스변수이다.

 

💻 출력

x = 1, y = 1
x = 1, y = 2
x = 1, y = 3
x = 1, y = 4
x = 1, y = 5
x = 1, y = 6
x = 1, y = 7
x = 1, y = 8
x = 1, y = 9
x = 1, y = 10

인스턴스변수 x는 인스턴스가 생성될때마다(위의 소스코드의 경우, main메서드 안에서 반복문 수행 중 계속 인스턴스 생성) 0으로 초기화(자료형이 int이므로)되므로 add()메서드를 수행할 때마다 항상 1이 나오는 것을 확인할 수 있다.

 

하지만 클래스변수 y는 클래스가 처음 로딩될 때 단 한번만 0으로 초기화되므로 main메서드 안에서 반복문 수행 중 계속 인스턴스를 생성하더라도 초기화되지 않기 때문에 값이 계속 누적된다는 사실을 확인할 수 있다.


초기화 블럭

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

클래스 초기화블럭: 클래스가 메모리에 처음 로딩될 때 단 한번만 수행

인스턴스 초기화블럭: 인스턴스가 생성될 때마다 수행

 

 입력

public class HaaLand {
    static {  // 클래스 초기화 블럭
        System.out.println("초기화 블럭입니다");
    }
    

    {  // 인스턴스 초기화 블럭
        System.out.println("인스턴스 블럭입니다");
    }
    
    
    public HaaLand() {
        System.out.println("생성자입니다");
    }

    public static void main(String[] args) {
        System.out.println("첫번째 블럭 테스트중입니다");
        HaaLand h1 = new HaaLand();

        System.out.println("두번째 블럭 테스트중입니다");
        HaaLand h2 = new HaaLand();
    }
}

💻 출력

초기화 블럭입니다
첫번째 블럭 테스트중입니다
인스턴스 블럭입니다
생성자입니다
두번째 블럭 테스트중입니다
인스턴스 블럭입니다
생성자입니다

코드가 실행되면서 클래스 HaaLand가 메모리에 로딩이 될 때, 클래스 초기화 블럭이 가장 먼저 수행되어 "초기화 블럭입니다"가 제일 먼저 출력된다. 그 후, main메서드가 수행되어 HaaLand 인스턴스가 생성되면서 인스턴스 초기화 블럭이 먼저 수행되고 다음으로 생성자가 출력된다.

 

위의 소스코드 출력 결과에서도 알 수 있듯이, 클래스 초기화 블럭은 처음 메모리에 로딩될 때 한번만 수행되고 인스턴스 초기화 블럭은 인스턴스가 생성될 때마다 수행된다는 사실을 확인할 수 있다.


 입력

class Product {
    static int count;
    int serialNo;

    {   // 인스턴스 초기화 블럭
        ++count;
        serialNo = count;
    }
}
public class ProductTest {
    public static void main(String[] args) {
        Product p1 = new Product();
        Product p2 = new Product();
        Product p3 = new Product();

        System.out.println("p1의 제품번호(serialNo)는 " + p1.serialNo);
        System.out.println("p2의 제품번호(serialNo)는 " + p2.serialNo);
        System.out.println("p3의 제품번호(serialNo)는 " + p3.serialNo);
        System.out.println("생산된 제품의 수는 모두 " + Product.count + "개입니다."); // count는 클래스변수이므로 클래스이름.클래스변수
    }
}

 Product 클래스의 인스턴스를 생성할 때마다 인스턴스 초기화 블럭이 수행된다.

인스턴스 초기화 블럭이 수행되어 클래스변수인 count의 값을 1 증가시키고 그 값을 인스턴스변수 serialNo에 저장하는 방식으로 작동된다.

 

💻 출력

p1의 제품번호(serialNo)는 1
p2의 제품번호(serialNo)는 2
p3의 제품번호(serialNo)는 3
생산된 제품의 수는 모두 3개입니다.

count를 인스턴스 변수로 선언했다면 결과는 어떻게 출력될까?

 

 입력

class Product {
    int count;
    int serialNo;

    {   // 인스턴스 초기화 블럭
        ++count;
        serialNo = count;
    }
}
public class ProductTest {
    public static void main(String[] args) {
        Product p1 = new Product();
        Product p2 = new Product();
        Product p3 = new Product();

        System.out.println("p1의 제품번호(serialNo)는 " + p1.serialNo);
        System.out.println("p2의 제품번호(serialNo)는 " + p2.serialNo);
        System.out.println("p3의 제품번호(serialNo)는 " + p3.serialNo);
    }
}

💻 출력

p1의 제품번호(serialNo)는 1
p2의 제품번호(serialNo)는 1
p3의 제품번호(serialNo)는 1

count를 인스턴스 변수로 선언할 경우, 인스턴스가 생성될 때마다 0으로 초기화되기 때문에 모든 Product 인스턴스의

제품번호는 항상 1이 출력된다.

 

! 중요 !

멤버변수는 자동으로 초기화되므로 초기화하지 않고도 값을 참조할 수 있다.

지역변수는 사용하기 전에 반드시 초기화하여야 한다.

같은 클래스 내의 메서드는 서로 객체의 생성이나 참조변수 없이 직접 호출이 가능하다.

static 변수의 초기화에 인스턴수변수를 사용할 수 없다. 사용하려면, 객체를 생성한 후 인스턴스변수를 사용해야 한다.

static 메서드에서는 인스턴스변수, 인스턴스메서드를 사용할 수 없다. 

인스턴스 메서드에서는 클래스변수나 클래스메서드를 사용하는 것은 가능하다.

 

 

 

 

/

5/7

 

 

'Back-End > JAVA' 카테고리의 다른 글

[Java] JDBC (1) (eclipse와 Oracle, MySQL)  (0) 2023.03.23
[Java] 접근 제어자  (0) 2023.03.19
[Java] (중요) 참조형 반환타입의 메서드  (0) 2023.03.18
[Java] 쓰레드  (0) 2023.03.13
[Java] Generic  (0) 2023.03.12