메이쁘

[JAVA] JAVA에서 static(정적) 변수 / 메서드 / 클래스 등 static 키워드란 ? 본문

Language/JAVA

[JAVA] JAVA에서 static(정적) 변수 / 메서드 / 클래스 등 static 키워드란 ?

메이쁘 2020. 8. 26. 00:44

안녕하세요.

 

JAVA 를 처음 접하게 되면 볼 수 있는

 

public static void main(String args[]) {}

 

여기서 static은 무슨 의미를 갖고 있을까요?

 

 

또는

 

static int a = 10;

 

여기에서도 사용되는 static은 무슨 의미를 갖고 있을까요?

 

 

JAVA에 사용되는 static 키워드에 대해 알아보겠습니다.

 

 

 

 

static (정적) 의 역할


  -  보통 static 은 "정적" 을 뜻합니다.  또한, 변수 / 메소드 / 클래스 앞에 "static" 을 붙여서 사용합니다.

class MainClass {
  
  // static 변수
  static int a = 10;
  
  // static 메소드
  static int getA() {
    return a;
  };
  
  // static 클래스 (클래스 내부에 static 클래스를 정의함)
  static class InnerStaticClass {}
}

  -  static 을 클래스에 사용하는 경우는 중첩 클래스(Nested class) 에 사용되므로, 이는 다른 포스트에서 다루겠습니다!

  

  -  이런 방식으로 사용합니다.

 

 

 

일반 변수와 static 변수의 차이

class A { 
  int a = 10;
  static int b = 10;
}

  -  이렇게 클래스 내에 멤버 변수(지역 변수) 와 static 변수가 존재한다고 가정합니다. 이 두 변수의 차이는 무엇일까요? 차이를 알기 위해서는 자바 프로그램이 실행하는 과정을 대략적이라도 알아야 합니다. (별도 포스트에서 다루겠습니다.)

 

  설명드리자면, Java는 JVM을 통해 Java 코드를 OS 환경 위에서 실행할 수 있습니다. 이 때, Runtime Data Area (보통 런타임이라고 부릅니다.) 안에 Method Area(Static Area), Heap Area 가 포함되어있죠.

 *** 이는 메모리 영역입니다.

 

  여기서, 멤버 변수(클래스 내 지역변수) 는 인스턴스 생성 시(new 키워드를 통한 객체 생성 / 할당) 인스턴스와 함께 Heap 영역 안에 메모리를 할당받습니다. 이 멤버 변수는 인스턴스 메모리 내에 함께 할당받아있죠.

즉, 인스턴스 생성 시 Heap 영역에 메모리를 할당받게 되며, 인스턴스에 접근해야지 해당 멤버 변수를 사용할 수 있습니다.

 

 

  반면, static 변수는 멤버 변수와는 다르게 Method Area(Static Area) 에서 메모리를 할당받습니다. 또한, static 키워드는 프로그램 실행 시 JVM에서 미리 Method Area에 메모리를 할당받아놓습니다.

그렇기 때문에, static 변수는 프로그램 실행 시 메모리 할당 /// 프로그램 종료 시 메모리 삭제 가 이루어집니다.

 

 *** 이러한 이유로 static 키워드를 많이 사용하게 되면 메모리 초과, 속도 저하 등 문제가 발생할 수 있기에 적당히 사용해야 합니다.

 *** Method Area(Static Area) 에는 클래스, static 키워드 들이 메모리를 할당받음. (정적 할당)

 *** Heap Area 에는 객체(인스턴스) 들이 메모리를 할당받음. (동적 할당)

 

 

  그래서 만약 객체를 n개 생성한다면, 멤버 변수 또한 Heap 영역의 객체 메모리 내부에 n개를 할당받게 되죠.

 

  하지만, static 변수는 프로그램 실행 시 단 1개만 Method 영역에 메모리를 할당받습니다.

 

  이해되셨나요?

 

 

  그 결과로, 메모리 할당 영역 및 할당 시간의 차이가 있기 때문에 각각의 변수에 대한 접근 방식이 다릅니다.

 

 

접근 방법

class A {
  int a = 10;
  static int b = 20;
}

class MainClass {
  public static void main(String args[]) {
    A tempA = new A();
    
    System.out.println(A.a); // 인스턴스 생성 없이 멤버 변수 직접 접근 불가능.
    System.out.println(A.b); // static 변수이기 때문에 인스턴스 생성 없이 직접 접근 가능함.
    
    System.out.println(tempA.a); // 가능
    System.out.println(tempA.b); // 가능하지만 권장하지 않음. 
  }
}

  -  static 변수는 별도의 인스턴스 생성 없이 클래스 이름으로 직접 접근할 수 있습니다.

 

  -  또한, 인스턴스에서 호출은 가능합니다만 굳이 권장하지 않습니다. 그 이유는 말안해도 아시겠죠? 

 

 

 

 다른 하나의 예시 코드를 보여드리겠습니다.

class MainClass {
  int a = 10;
  static int b = 20;
  
  // static -> non-static 호출 : 불가능(X)
  static int getNumber() {
    return a;
  }
  
  // static -> static 호출 : 가능(O)
  static int getNumber() {
    return b;
  }
  // non-static -> non-static 호출 : 가능(O)
  int getNumber() {
    return this.a;
  }
  
  // non-static -> static 호출 : 가능(O)
  int getNumber() {
    return b;  // this는 불가능
  }
}

  -  this는 현재 객체를 가리킵니다. 그렇기 때문에, 프로그램 실행 시 메모리를 할당받은 static 변수에는 this를 사용할 수 없습니다.

 

  -  static 메소드 내에서 non-static(멤버 변수) 사용은 불가능합니다. 그 이유는 위에서 말햇듯이 프로그램 실행 시 메모리에 할당되는데, 실행할 때 멤버 변수 a 는 메모리에 할당되어 있지 않기 때문에 참조할 수가 없는 것이죠.

 

 

 

활용 방안

  -  정말 무수히 많지만, 대표적으로 몇개 꼽자면

 

    ->  전역 변수

    ->  Util 클래스(예를 들어, 문자열을 포맷하는 함수, 날짜 출력하는 함수 등)

    ->  Singleton 패턴 (디자인 패턴 중 하나. 단 하나의 인스턴스로 설계하는 방식)

 

가 있습니다.

 

 

 

 

 

궁금한 점, 틀린 곳이 있다면 댓글 부탁드립니다.

 

감사합니다!

Comments