ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] static 변수에 대해서 알아보자 (실전편)
    백엔드/부족한 기본 정리 2020. 8. 25. 23:12

          로재의 개발 일기       

    정적변수 간접 체험해보기

    앞선 이론편에서 설명한 Static 예약어

    클래스 변수 혹은 정적 변수라고 불립니다.


    그런데 왜 자바에서는 메인문이 항상

    public static void main으로 시작할까요?


    아시는 분은 그냥 스킵...


     메모리 로딩 순서

     변수

    생성 시기 

    소멸 시기 

    메모리 영역 

    호출 사용법 

     클래스 변수

    클래스가 메모리에 올라감 

    프로그램 종료 (서버 종료) 

    메소드 영역 

    클래스 이름, 인스턴스의 변수 이름

     인스턴스 변수

    인스턴스가 생성됌 

    인스턴스가 소멸됌 

    힙 영역 

    인스턴스 이름, 변수 이름 

     지역 변수

    블록 안에서 변수가 선언됌 

    블록을 나올때 

    스택 영역 

    변수 이름 

    자바의 메모리 로딩 순서는 다음과 같으며 static의 경우에는 클래스 변수에 해당하게 됩니다.

    (제가 알기로는 프로그램 시작하면 클래스가 자동으로 메모리 영역에 담겨지는 것으로 알고 있습니다만 ..)


    클래스 변수에 접근하기 위해서는

    1. 클래스를 통해서 접근 

    ClassName.class-variable

    2. 인스턴스의 변수를 통해서 접근이 가능합니다.

    ClassName obj = new ClassName();

    obj.class-variable


    간단한 예시를 살펴보죠.


     예제1

    학생 클래스

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    package com.rojae.example.student;
    public class Student {
        // static 변수를 선언한다
        public static int serialNumber = 1000;
        public int studentID;
        public String studentName;
        public int grade;
        public String address;
        
        public String getStudentName() {
            return this.studentName;
        }
        
        public void setStudentName(String name) {
            this.studentName = name;
        }
    }
     
    cs

    학생 클래스를 생성한 소스코드입니다. 

    (데이터 전송 객체라고 해도 좋겠네요)


    위의 경우 static으로 선언이 되어

    클래스 변수인 serialNumber의 값은 1000으로

    고정되게 됩니다.


    Main 문

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    package com.rojae.example.application;
     
    import com.rojae.example.student.Student;
     
    public class MainTest {
        public static void main(String args[]) {
            Student student1 = new Student();
            student1.setStudentName("학생이름1");
            System.out.println(student1.serialNumber);    // 1000
            student1.serialNumber++;                    // 1001
            
            Student student2 = new Student();            // static serialNumber 공
            student2.setStudentName("학생이름2");            
            
            System.out.println(student1.serialNumber);    // 1001
            System.out.println(student2.serialNumber);    // 1001
        }
    }
     
    cs

    위의 경우에는 값이 공유되기 때문에

    인스턴스 변수인 student1과 student2가

    같은 serialNumber를 가진다는 것을 알 수 있습니다.


    영원히 죽지 않는 서버라면

    데이터베이스의 auto_increment = 1을 

    이렇게 개발할 수 있겠네요.

    (과연 서버 부하는 양호할 것인가)


    하지만 아래의 경우에 동작할까요..?

      // static 변수를 선언한다
        private static int serialNumber = 1000;
       


    정답은 정상적으로 동작하지 않습니다.

    메인 클래스에서 접근이 불가능하기 때문이죠.



    하지만 만약에 직접적으로 메인클래스에서 

    private로 선언된 값을 바꾸려는

    다음과 같은 시도가 아니라, 

            
    student1.serialNumber++;            // 1001




    아래과 같은 시도였다면 

    클래스 내부에서 serialNumber를 연산하게 됩니다.

            
    student1.setSerialNumber(1001);    // 1001


    주로 학생 클래스 내부에 

    " public  setSerialNumber " 그리고 "public getSerialNumber "

    메소드를  추가하여

    수정이 가능할 것입니다.


    혹은 1만큼 증가시키고자 한다면

    클래스 내부의 메소드를 통해서 

    값을 증가시켜야 하는 것이죠.


    이는 public, private, protected의 차이로 이어집니다.

    (접근 제한자는 여기까지만 언급하겠습니다)


     예제 2

    static 변수가 있다면, static 메소드

    클래스 메소드가 존재합니다.


    이번에는 serialNumber 변수를 사용하는 메소드를 만들어보고

    메모리 로딩 오류에 대해서 예시를 들어보겠습니다.


    우선 static 변수를 private로 바꿔주겠습니다.

    더불어 static 메소드 (클래스 메소드) 추가를 해주었습니다.


    학생 클래스

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    package com.rojae.example.student;
     
    public class Student {
        // private로 변경 
        private static int serialNumber = 1000;
        public int studentID;
        public String studentName;
        public int grade;
        public String address;
        
        public String getStudentName() {
            return this.studentName;
        }
        
        public void setStudentName(String name) {
            this.studentName = name;
        }
     
        public static int getSerialNumber() {
            return serialNumber;
        }
     
        public static void setSerialNumber(int serialNumber) {
            Student.serialNumber = serialNumber;
        }
        
        
    }
     
    cs


    Main 문

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    package com.rojae.example.application;
     
    import com.rojae.example.student.Student;
     
    public class MainTest {
        public static void main(String args[]) {
            Student student1 = new Student();
            student1.setStudentName("학생이름1");
            student1.setSerialNumber(1001);                // set 1001
            
            Student student2 = new Student();            // static serialNumber
            student2.setStudentName("학생이름2");            
            
            System.out.println(student1.getSerialNumber());    // 1001
            System.out.println(student2.getSerialNumber());    // 1001
        }
    }
     
    cs


    정상적으로 동작하였습니다.



    혹시 다음으로 바꿔주면 동작을 할까요..?


    학생 클래스 (클래스 메소드 내부의 클래스 인스턴스 변수)

    1
    2
    3
    4
        public static int getSerialNumber() {
            grade = 1;
            return serialNumber;
        }
    cs


    static 변수에 클래스의 멤버변수 (인스턴스 변수)를 넣어주었지만

    에러가 발생한다.


    그 이유로는 메모리 로딩 순서가


    클래스 변수와 클래스 메소드의 메모리 할당이 이뤄진 이후에

    클래스의 인스턴스 변수들도 메모리 할당이 이루어지기 때문이다.


    즉 static 메소드는 grade라는 변수를 알 수 없는 것이다.




    이때 문제 

    아래 클래스 메소드에서 static을 제거하면

    정상적으로 동작할까..?

    public static int getSerialNumber() {
            return serialNumber;
        }
     
        public static void setSerialNumber(int serialNumber) {
            Student.serialNumber = serialNumber;
    }



    다음 편에서 

    public static void main 설명!



    마무리

    글 쓴다고 아래 같이 하려다 ... 말았습니다.. 

    (글 쓰려 억지로 짜는 소스코드..)

        student1.setSerialNumber(student1.getSerialNumber() + 1);                // 1001




    - 다음 글 -  

    > [Java] 아직입니다 <


    반응형
Designed by Tistory.