---------------------------------------------------------------------------------------------------

변수의 static과 메소드의 static은 다르다!!!

---------------------------------------------------------------------------------------------------

 

1. 변수의 static

  • "변수를 저장하는 방법을 static이다" 라는 것!
  • 즉, stack의 영역에 저장되어 메소드가 끝이나면 사라지는 변수가 아니라
  • method area 영역에 저장되어 메소드가 끝이나더라도 사라지지 않는 변수의 특성을 말한다.
  • static 공통적으로 같은 값을 갖고 있고 수정의 필요가 없을 때 사용하므로 ​보통 final과 함께 쓰이는 경우가 많다.


 1.1 장점​

  • static 키워드를 붙이면 자바는 메모리 할당을 딱 한번만 하게 되어 메모리가 절약된다.
  • heap영역이 아니므로 가비지 컬렉터가 수거하지 않고 계속 메모리에 남아있다.
  • stack영역이 아니므로 class 또는 instance가 끝남과 동시에 메모리에서 사라지지 않는다.

 

1.2 단점

  • 메모리가 계속 남아있으므로 잘못사용할 시, 메모리가 낭비될 수 있다.

 

1.3 언제 사용하는가?

  • 여러개의 인스턴스가 동일한 값을 저장하는 변수를 갖고 있을 때, static으로 저장한다.


ex) 계산기를 만드는 클래스 Calurlator가 있다면, 각각의 결과값을 저장하는 result라는 변수는 static이 필요하지 않지만,

만약 모든 계산기의 이름이 "카*오"라는 이름을 갖고 있는 것을 저장한다면 static을 이용하여 method area에 저장한다. 

1) 그냥 선언할 경우

2) static으로 선언할 경우

public class Test{

   class Calulator{

      int result;

     String calName = "카*오";

   

      void plus(int value){  

         this.result += value;

      }

  }

   public static void main(String[] args){

      Calulator c1 = new Calculator();

      Calulator c2 = new Calculator();

   }

}

 

public class Test{

   class Calulator{

      int result;

     static String calName = "카*오";

   

      void plus(int value){  

         this.result += value;

      }

  }

   public static void main(String[] args){

      Calulator c1 = new Calculator();

      Calulator c2 = new Calculator();

   }

}

 Calulator로 인스턴스를 만들때마다 heap 영역에 calName이라는 공간이 쌓이게 된다. 만약 Calulator 인스턴스를 100개를 만든다면 100개의 "카*오"라는 동일한 값을 갖는 calName이 생긴다는 것이다

=> 메모리낭비

 claName을 static로 선언했으므로 method area영역에 한번만 메모리가 생성되고 만약 Calulator 인스턴스를 100개를 만든다면 하나의 calName을 서로 공유하게 된다

=> 메모리 효율적 관리 가능 

 

 

 

2. 메소드의 static

  • 메소드의 static은 어떻게 호출할 것인가 방법에 대한 것.
  • 즉, 함수 호출시 클래스로 호출할 것인가 아니면 인스턴스로 호출할 것인가에 문제
  • static 메소드의 변수는 메소드가 호출되지 않아도 method area영역에 변수의 메모리가 생성된다.
  • static메소드는 메소드를 호출하지 않아도 static 메소드안의 변수와 메소드가 JVM에 올라간다.
  • staic이 붙지 않는다면 instance method​

 

2.1 언제 사용하는가?

 1) 그냥 선언할 경우

 2) static으로 선언할 경우

public class NomalTest{

   public void printTest(){  

         System.out.println("Instance Method");

    } 

}

-----------------------------------------------------------

public class Test{

   public static void main(String[] args){

      NomalTestc1 = new NomalTest(); //객체 생성

      n1.printTest();

}

 public class StaticTest{

   public static void printTest(){  

         System.out.println("Static Method");

    } 

}

-----------------------------------------------------------

public class Test{

   public static void main(String[] args){

       StaticTest.printTest();

   }

}

  •  class이름으로 호출불가!
  • 인스턴스 이름으로 호출하여야함
  • plus함수 호출시 호출한 객체의 시작변수를 담고있는         히든변수 this가 생성됨
  • StaticTest.printTest();로 호출가능
  • "new"를 통해 객체 생성 필요X

 

* 2)번 보다는 1)번을 선호한다.

* .java 파일에서 .class로 컴파일 될 때, static 메소드들은 먼저  method area 메모리에 적재된다. 따라서 불필요한 method에 static을 붙일경우,

  불필요한 메모리 낭비가 일어날 수 있다.

 

 

2.2 main은 왜 반드시 static일까?

main method를 호출하는 명령어는 누구도 존재하지 않는다. 때문에 호출되지 않고도 변수와 method가 JVM에 위치하게 하려면 static이여야 하는 것이다.(static메소드는 메소드를 호출하지 않아도 static 메소드안의 변수와 메소드가  JVM에 생성되므로)
=> 따라서, main은 static을 쓴다!!

 

그렇다면 다른 method도 전부 static으로 하면 편하지 않을까?

아니다!! 만약, 다른 함수들도 static으로 선언된다면, 모든 method의 변수가 전부 다 JVM에 쌓이고 상주하므로 overflow가 발생하게 된다.

 

따라서, 적시적소에 static을 붙이는 것이 중요하다.   

 

 

3. static block

  • 클래스가 로딩된 후 클래스 변수를 초기화 하는 용도로 사용
  • 클래스 로딩은 단 한 번만 이루어지므로 static 블럭도 단 한번도 실행된다.
  • 실행순서: ​클래스 로딩 -> 클래스 변수 준비 -> static block 실행

 

3.1 쉬운 satic block 예시

< 예제코드 >

 public class Test45 {
   public static void main(String[] args) {
   
   System.out.println("클래스는 언제 로딩될까? => 1");
   ClassA obj1;
   System.out.println("클래스는 언제 로딩될까? => 2"); 
  

   //아래의 출력결과를 보면 1, 2사이에 클래스 로딩되었으므로 new를 하려고 할 때 해당 클래스가 없다면 로딩되는 것을 알 수 있다.
   obj1 = new ClassA();     
   System.out.println("클래스는 언제 로딩될까? => 3");
  
   System.out.println(ClassA.value);
 }
}

 public class ClassA {
   static int value = 100;
 
   static{
      System.out.println("ClassA의 static 블럭실행");
      value = 200;
   }
   static{
      System.out.println("static 블럭이 여러개일 경우 순차적으로 실행");
   }
}

 

< 출력결과 >

 클래스는 언제 로딩될까? => 1
 클래스는 언제 로딩될까? => 2
 ClassA의 static 블럭실행
 static 블럭이 여러개일 경우 순차적으로 실행
 클래스는 언제 로딩될까? => 3
 200 

 


4. 첨부

JVM.pptx


+ Recent posts