[Java] Static 완전정복!! (2)

About Static

Posted by JongMin-Lee on June 15, 2019

들어가며

저번 글에서는 static에 대해 간단하게 알아보았습니다. (안보고 오셨다면 여기로! -> static 완전정복(1))

지금까지의 내용을 요약해보자면 프로그램이 실행될 때 Java메모리에 할당되며, 프로그램이종료될 때 해체된다. 또한 main메소드에서 사용하는 이유는 JVM에 편의를 제공하기 위함이라 할 수 있겠습니다.

이번에는 static을 사용하는 다양한 경우에 대해 보겠습니다!!


Static초기화 블록(Initailization BLock)

Static 변수(Variables)

Static 메소드

이들은 클래스의 static 멤버 또는 구성요소 입니다. 이들은 액세스 하기 위해서 객체를 만들 필요가 없습니다. 즉, 직접 클래스의 이름을 사용하여 액세스 할 수 있습니다.

Static 초기화 블록은 Static 변수만을 초기화하는 이름없는 블록입니다. 다음과 같은 형태를 가집니다.

1
2
3
static{
    // Set of Statements
}

아래의 코드를 보며 이들의 동작을 자세히 알아 봅시다!!

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
class StaticComponents{
    static int staticVariables;

    static{
        System.out.println("StaticComponents SIB");
        staticVariable = 10;
    }
    
    static void staticMethod(){
        System.out.println("From StaticMethod");
        System.out.println(staticVariable);
    }
}

public class MainClass{
    static{
        System.out.println("MainClass SIB");
    }

    public static void main(String[] args){
        // Static Members directlyaccessed with Class Name
        StaticComponents.staticVariable = 20;
        StaticComponents.staticMethod();
    }
}

1단계

Java MainClass 를 트리거하면 Java명령은 할당된 메모리를 Stack과 Heap으로 나누게 됩니다. 자바 명령어는 Stack메모리에 들어가 실행되며, MainCalss가 heap메모리에 있는지 없는지 확인합니다. 만약 heap에 없다면 load하는 작업을 수행합니다. 그렇게 되면 MainClass는 무작위로 조금의 메모리를 할당받게 됩니다. 이것을 Class Memory라 부릅니다. 모든 static멤버는 이 Class메모리에 load됩니다. MainClass 안에는 오직 하나의 static 메소드(main)만 있기 때문에 이것을 MainClass의 Class메모리에 load시킵니다.


2단계

모든 static 멤버를 load한 후 정적 초기화 블록(SIB: Static Initailization Blocks)이 실행됩니다. 이들은 임무를 수행한 후 저장되지 않습니다. 다음을 보면 확실하게 알 수 있습니다!

Main()메소드를 로드한 후 MainClass의 SIB는 실행을 위해 Stack에 들어갑니다. 여기서 SIB에는 하나의 문장만 있습니다.

1
2
3
static{
    System.out.println("MainClass SIB");
}

이 부분을 실행해서 ‘MainClass SIB’를 콘솔창에 띄운 후 Stack메모리에서 벗어납니다.


3단계

이제 java command(자바 명렁어)는 실행을 위해 main메소드를 호출합니다.(main메소드가 스택에 들어갑니다.) 가장 먼저 StaticComponents.staticVariable=20; 가 실행됩니다. 여기서 먼저 StaticComponents 클래스가 메모리에 load되었는지 확인합니다. load되어 있지 않으면 먼저 load작업을 수행합니다. 임의의 메모리가 StaticComponents클래스에 할당되면 StaticComponents의 모든 정적 멤버(변수, 메소드)가 Class 메모리에 load됩니다. StaticVariable은 전역변수이고 기본값은 0(초기화)으로 할당됩니다.


4단계

StaticComponents의 모든 static 멤버를 load하면 SIB가 실행됩니다. 마찬가지로 StaticComponents클래스의 SIB가 실행을 위해 Static에 들어갑니다. 가장 먼저 System.out.println("StaticComponents SIB");가 실행됩니다. 콘솔에 ‘StaticComponents SIB’을 띄운 후 staticVariable에 10이라는 값을 넣어 줍니다. 이제 다른 명령문이 없으므로 스택 메모리에 남겨 둡니다.


5단계

이제 main()메소드로 돌아옵니다. 이제 staticVariable변수에 20의 값을 할당해주는 명령이 실행됩니다. 그 다음 staticMethod()를 호출합니다.


6단계

호출된 staticMethod()는 실행을 위해 stack에 들어갑니다. 첫 번째 문장을 수행하여 콘솔에 ‘From staticMethod’을 출력한 후 staticVariable의 값 20을 출력합니다. 더 이상 명령문이 남아 있지 않기 때문에 stack을 떠납니다.


7단계

다시 main()으로 돌아오면 더이상 수행할 명령어가 남아있지 않습니다. 따라서 main()메소드와 java command는 stack을 떠납니다.

위의 과정을 그림으로 나타내면 다음과 같습니다.

출력순서는 다음과 같습니다.

1
2
3
4
MainClass SIB
StaticComponents SIB
From StaticMethod
20


마치며

사실 Static은 이보다 더 많은 곳에 사용이 됩니다. 예를 들어 final을 활용하거나, import할 때도 사용이 됩니다. 그러나 지금까지의 글을 알고 있다면 어느 곳에서 사용이 되도 이 붙은 static이 무엇을 의미하는지, static이 붙음으로써 변수, 메소드가 어떠한 의미를 갖게 되는지 알 수 있을 것입니다. 부족한 글이지만 읽어주셔서 감사합니다!!


참고

이미지 : https://www.javatpoint.com/static-keyword-in-java

https://javaconceptoftheday.com/static-members-java/