ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java - Object4
    개발언어/JAVA 2023. 10. 17. 11:19

    static 변수

    여러 클래스에서 공통으로 사용하는 변수를 'static 변수'로 선언한다.

    static 변수의 정의와 사용방법

    static 변수란 다른 용어로 '정적 변수'라고 한다. static 변수는 자바뿐만 아니라 언어에서도 비슷한 개념으로 사용하고 있는 변수로서 자바에서는  다른 멤버 변수처럼 클래스 내부에 선언한다. 변수를 선언할 때 다음과 같이 자료형 앞에 static 예약어를 사용한다.

    static 변수는 클래스 내부에 선언하지만, 다른 멤버 변수처럼 인스턴트가 생성될 때마다 새로 생성되는 변수가 아니다. static 변수는 프로그램이 실행되어 메모리에 올라갔을때 딱 한 번 메모리 공간이 할당된다. 그리고 그 값은 모든 인스턴스가 공유한다.

     

    다시 설명하면 일반 멤버 변수는 인스턴스가 생성될 때 마다 새로 생성되어 각각 다른 studentName을 가지게 되지만, static으로 선언한 변수는 인스턴스 생성과 상관없이 먼저 생성되고 그 값을 모든 인스턴스가 공유한다. 이런 이유 때문에 static 변수를 클래스에 기반한 변수라고 해서 '클래스 변수(class variable)'라고도 한다.

     

    static 변수 사용하기

    package studystatic
    
    public class Student{
    // static 변수는 인스턴스 생성과 상관 없이 먼저 생성된다.
        public static int serialNum = 1000
        public int studentID;
        public String studentName;
        public int grade;
        public String address;
        
        public String getStudentName(){
        	return studentName;
        }
        
        public void setStudentName(String name){
        	studentName = name;
        }
        
    
    }

    static 변수 테스트하기

    package studystatic;
    
    public class StudentTest{
    	public static void main(String[] args){
        	Student studentLee = new Student();
            studentLee.setStudentName("이지원");
            //seriaNum 변수의 초기값 출력
            System.out.println(studentLee.serialNum); //1000
            //static 변수 값 증가
            studentLee.serialNum++;
            
            Student studentSon = new Student();
            studentSon.setStudentName("손미나");
            //증가된 값 출력
            System.out.println(studentSon.serialNum); //1001
            System.out.println(studentLee.serialNum); //1001
        }
    }

    studentLee를 먼저 생성하고 이 참조 변수를 사용하여 전체 인스턴스에서 공통으로 사용하는 멤버 변수 serialNum 변수 값을 1증가 시킨다. 그리고 studentSon을 생성한다. 생선된 studentSon으로는 아무 연산도 수행하지 않는다. 그다음에 studentSon과 studentLee로 serialNum 변수 값을 출력해 보면 둘 다 1001로 증가된 serialNum값이 출력되는 것을 알 수 있다. 즉 두개의 참조 변수가 static 변수에 대해 동일한 변수의 메모리를 가리키고 있다는 것을 알 수 있다.

    클래스 이름으로 static 변수 참조

    System.out.println(Student.seriaNum); //1001

    앞서도 말했듯이 static변수는 인스턴스 생성과는 별개이므로 인스턴스보다 먼저 생성된다. 그러므로 인스턴스가 아닌 클래스 이름으로도 참조 하여 위코드 와 같은 형태로도 사용할수 있으면 자바에서는 static 변수를 클래스 변수라고 한다.

    자바에서 static 변수를 클래스 변수라고 하는 이유는 인스턴스마다 생성되는 변수가 아니라 클래스에 속해 한번만 생성되는 변수이고 이를 여러 인스턴스가 공유하기 때문이다.

     

    클래스 메서드

    package studystatic
    
    public class Student{
    // private 변수로 변경
        private static int serialNum = 1000
        public int studentID;
        public String studentName;
        public int grade;
        public String address;
        
        public Student(){
        	serialNum++;
            studentID = serialNum;
        }
        
        public String getStudentName(){
        	return studentName;
        }
        
        public void setStudentName(String name){
        	studentName = name;
        }
    	
        public static int getSerialNum(){
        	int in = 10;
            return serialNum;
        }
        
        //serialNum의 get()메서드
        public static void setSerialNum(int){
        	int i = 10;
            return serialNum;
        }
        
        //serialNum의 set()메서드
        public static void setSerialNum(int serialNum){
        	// this는 인스턴스를 뜻하므로 클래스 이름인 Student를 사용한다.
        	Student.serialNum = serialNum;
        }
    }

    일반 멤버 변수를 위한 메서드가 존재하듯이 static 변수를 위한 메서드도 있다. 이런 메서드를 'static 메서드' 또는 클래스 메서드(class method)라고 한다. 일단  위 코드에서 serialNum 변수를 사용하는 메서드를 static메서드로 만들어 보자. 그러기 위해선 우선 serialNum 변수를 직접 참조하지 못하도록 private 변수로 선언한다. 

     

    위와 같이 코드를 작성하면 외부 클래스에서 serialNum값을 사용하려면 get()메서드를 호출하고, serialNum변수 값을 변경하려면 set()메서드를 사용해야한다. 

     

    클래스 메서드와 인스턴스 변수

    public class Student{
    	private static int serialNum = 1000;
        int studentID;
        String studentName;
        int grade;
        String address;
        
        ...
        public static int getSerialNum(){
         int i = 10;
         //오류
         ⛔️studentName = "박지원"; //클래스 메서드 내부에서는 인스턴스 변수 사용 불가
         return serialNum;
        }
    }

    클래스 메서드 내부에서는 인스턴스 변수를 사용할 수 없다. getSerialNum()메서드는 static 예약서를 붙인 클래스 메서드이다. 위 코드에서는 해당 메서드에서 세 종류의 변수를 사용하고 있다.

     

    일단 가장 먼저 선언한 int i를 살펴 보자. 이 변수는 메서드 내부에서 선언하였다. 이렇게 선언한 변수는 지역변수(local variable)라고 한다. 지역 변수는 메서드가 호출될 때 메모리에 생성되어 메서드가 끝나면 사라지는 변수이다. 따라서 이 변수는 getSerialNum()메서드 내부에서만 사용할 수 있다. 

     

    두번째로, 코드 마지막 return serialNum; 문장을 보면 serialNum 변수를 static 변수이기 때문에 클래스 메서드인 getSerialNum()메서드 내부에서도 사용할 수 있다.

    마지막으로 메서드 두번 째 줄에 사용한 studentName 변수는 오류가 발생한다. 이 변수는  Student클래스의 멤버 변수로, 인스턴스가 생성될 때 만들어지는 인스턴수 변수 이기 때문에 static 메서드 안에서 사용할 수 없는 것이다.

     

    클래스 메서드 사용해 보기

    package studystatic;
    
    public class StudentTest{
    	public static void main(String[] args){
        	System.out.println(Student.getSerialNum()); // 1000;
        }
    }

    Student.getSerialNum을 프린트 하는 코드를 살펴보면 알수 있듯이 클래스 메서드에 같은 경우 인스턴스가 생성되지 않아도 언제든지 호출할 수 있어야 하므로, 인스턴가 생성되어야 메모리에 해당하는 인스턴스 변수를 저장할 메모리가 할당되는 인스턴스의 멤버 변수는 클래스 메서드 내부에서 사용할 수 없다. 추가로 일반 메서드에서 클래스 변수를 사용하는 건 전혀 문제가 되지않는다.

     

    변수 유형에 따른 용도

    변수 유형 선언 위치 사용 범위 메모리 생성과 소멸
    지역 변수
    (로컬 변수)
    함수 내부에 선언 함수 내부에서만 사용 스택 함수가 호출될 때 생성되고 함수가 끝나면 소멸함
    멤버 변수
    (인스턴스 변수)
    클래스 멤버 변수로 선언 클래스 내부에서 사용하고 private이 아니면 참조 변수로 다른 클래스에서 사용가능 인스턴스가 생성될 때 힙에 생성되고, 가비지 컬렉터가 메모리를 수거할 때 소멸됨
    static 변수
    (클래스 변수)
    static 예약어를 사용하여 클래스 내부에 성넌 클래스 내부에서 사용가능하고 private이 아니면 클래스 이름으로 다른 클래스에서 사용가능 데이터 영역 프로그램이 처음 시작할 때 상수와 함께 데이터 영역에 생성되고 프로그램이 끝나고 메모리를 해제할 때 소멸된다.

     

    [출저 - Do it! 자바 프로그래밍 입문 , 박은종]

    http://www.easyspub.co.kr/20_Menu/BookView/A001/267/PUB

     

    http://www.easyspub.co.kr/20_Menu/BookView/A001/267/PUB

     

    www.easyspub.co.kr

     

    댓글

Designed by Tistory.