본문 바로가기

Java

Java- 클래스 변수와 클래스 메소드, static

클래스 변수와 인스턴스 변수

 클래스를 선언하면 내부에 수많은 인스턴스 변수(일반적인 클래스 멤버 변수)를 선언하게 된다.  

그리고 클래스 변수란 static 선언된 변수를 의미한다. 일반적인 변수들과는 달리 클래스 변수는 하나의 메모리 공간에 존재하면서 단지 클래스의 인스턴스들이 해당 변수에 접근할 권한이 존재하는 것뿐이다. 따라서 클래스 변수는 모든 인스턴스들이 동시에 공유하는 변수라고 생각하면 편하다.

 

 클래스 변수란...

  -인스턴스 생성 이전부터 접근이 가능하다.

  -어느 인스턴스에도 속하지 않는다.

 

클래스 변수에 접근하기

 클래스 내부에서 접근

  -클래스 변수 이름

 

 클래스 외부에서 접근

  -인스턴스 이름.클래스 변수 이름

class AccessWay{
    //클래스 내부
    static int num = 0;
    AccessWay(){
        incrCnt();
    }
    void incrCnt(){
        num++;  //클래스 내부에서 이름을 통한 접근
    }
    void showInfo(){
        System.out.println("num: "+num);
    }
}

public class ClassVarAccess {
    public static void main(String[] args) {
        //클래스 외부
        AccessWay way = new AccessWay();
        way.showInfo();

        way.num++; //외부에서 인스턴스명.변수명을 통한 접근
        way.showInfo();

        AccessWay.num++;  //외부에서 클래스명.변수명을 통한 접근
        way.showInfo();
    }
}

 

클래스 변수의 생성과 초기화

 클래스 변수는 인스턴스가 생성되기 전에 이미 메모리 공간에 초기화되어 존재한다. 즉 예를들어 어떠한 클래스 A에 클래스 변수 num이 있다고 하자. 그러면 A의 인스턴스가 생성되지 않았다고 하더라도 이미 클래스 변수는 존재하는 상태여서 클래스 외부에서 클래스명.변수명으로 접근이 가능하다.

class AccessWay{
    //클래스 내부
    static int num = 100;  //인스턴스 생성 여부와 관계없이 num은 100으로 초기화되어 생성

    AccessWay(){  //생성자
        num = 0;  //인스턴스가 생성시 마다 0으로 초기화
    }
}

public class ClassVarAccess {
    public static void main(String[] args) {
        //클래스 외부
        AccessWay.num++;
        System.out.println("인스턴스 생성 전");
        System.out.println(AccessWay.num);

        AccessWay way = new AccessWay();  //생성자 실행. num이 0으로 초기화
        System.out.println("인스턴스 생성 후");
        System.out.println(AccessWay.num);
    }
}

인스턴스 생성 전
101
인스턴스 생성 후
0

 

 따라서 굳이 클래스변수를 사용하는 이유는 하나에 클래스엔 여러개의 인스턴스들이 동시에 존재할 수 있다. 각각의 인스턴스들마다 인스턴스 변수에는 다른 값들을 가지고 있을 것이다.

 그런 상황에서도 모든 인스턴스들이 동시에 공유 할 만한 데이터가 존재하는 경우 그 데이터만 따로 클래스 변수로 선언해둔다면 하나의 데이터만 있어도 여러개의 인스턴스들이 동시에 사용할 수 있다는 장점이 존재한다.

 

 만일 참조를 목적으로만 존재하는 클래스 변수가 있다면 그 경우에는 final 선언을 통해서 상수 취급을 해주면 더 좋다.

class Circle{
//참조를 목적으로만 존재하는 상수 PI
    static final PI = 3.14;  //상수 취급 + 인스턴스들 간 공유
    private int radius;      
    
    Circle(double r){
    	radius = r;
    }
}

클래스 메소드

  클래스 메소드도 클래스 변수와 마찬가지로 static 선언이된 메소드를 의미한다. 그리고 이 클래스 메소드도 인스턴스가 생성되기 이전에 생성이 되기 때문에 인스턴스의 선언 이전부터 "클래스명.클래스함수명"의 구조를 통해서 접근이 가능하다.

class AAA{
    static int sum(int a, int b){
    	return a+b;
    }
}

class MainClass{
	public static void main(){
    	AAA.sum(1,2);  //클래스 변수의 호출
    }
}

 

클래스 변수와 클래스 메소드 정리

 

  클래스 변수 클래스 메소드 인스턴스 변수 인스턴스 메소드
클래스 메소드에서의 접근 가능 여부 접근 가능 접근 가능 접근 불가 접근 불가
인스턴스 메소드에서의 접근 가능 여부 접근 가능 접근 가능 접근 가능 접근 가능
public class ClassMethodTest {
    int a = 10;
    static int b = 20;
    void instanceMethod(){
        a++;  //인스턴스 변수
        b++;  //클래스 변수
        classMethod();  //클래스 함수
    }
    static void classMethod(){
        //a++; 인스턴스 변수 접근 불가
        b++;  //클래스 변수
    }
    static void classMethod2(){
        //instanceMethod(); 인스턴스 메소드 접근 불가
        classMethod();  //클래스 메소드 접근 가능
    }
}

 

static 초기화 블록

  static 초기화 블록은 특정 중괄호 내부의 코드들이 가상머신이 클래스의 정보를 읽어 들일 때 실행이 된다. 

예를들어 어떠한 클래스 변수의 값을 인스턴스 변수의 값으로 초기화를 하고 싶다고 가정을 해보자.

일반적인 경우라면 클래스 변수가 생성되었을 시에는 인스턴스 변수는 생성되지 않았기에 정상적으로 작동하지 않는다.

그러나 static 초기화 블록을 사용하면 인스턴스 변수도 가상머신이 클래스를 로딩 시 같이 로딩된다.

 

import java.time.LocalDate;

public class DateOfExecution {
    static String date;
    static{  //클래스 로딩 시 단 한번 실행이 되는 영역
        LocalDate ndate = LocalDate.now();  //현재 시간을 읽어들이는 함수, ndate는 인스턴스 변수
        date = ndate.toString(); //인스턴스 변수로 클래스 변수를 초기화
    }
    public static void main(String[] args) {
        System.out.println(date);
    }
}

'Java' 카테고리의 다른 글

Java- 문자열 결합의 최적화(StringBuilder 클래스)  (0) 2022.12.27
Java- 메소드 오버로딩과 this  (0) 2022.12.26
Java- main 메소드  (0) 2022.12.26
Java- 접근 지시 제어자  (0) 2022.12.24
Java- 생성자  (0) 2022.12.22