re: java static과 private차이

iq_up
답변채택률77.8%
2013.05.27 22:08
답변 추천하기

static과 private차이를 물으셨는데.

우선 static과 static이 아닌 것의 차이를 설명드리겠습니다.

 

1. static이 붙고 안붙은 변수의 차이:

 

    public class Human{

       pulbic static long population;/*인구수 static이 붙었습니다.*/

       public int age;/*나이  static이 붙었습니다.*/

   }

 

   이런 클래스를 만들었습니다.

   인간의 인구수는 변수가 한개만으로 충분하겠지요? 그래서 static을 붙였습니다.

   그리고 나이라는 변수는 사람마다 나이가 틀리겠죠? 그래서 static을 붙였습니다.

 

   사용할 때는 아래와 같습니다.

  

  1.1 static인 변수에 값을 대입하기

   Human.population = 7000000000L;

       static이므로 new해서 인스턴스를 만들지 않고 direct Access해서 값을 대입하여 사용합니다.

       (long형자료형인 경우 숫자뒤에 L을 붙여야 하는거는 아시죠?)

 

  1.2 static이 아닌 변수에 값을 대입하기

 

   Human aMan = new Human();// 1.먼저 생성한 후

   aMan.age=26; // 2.대입합니다.

 

   Human aMan2 = new Human();// 1.먼저 생성한 후

   aMan2.age=27;// 2.대입합니다.

 

  System.out.println("두명의 나이를 더하면?"+ (aMan.age+aMan2.age));

 

      static이 아니므로 new로 인스턴스를 생성하여 해당인스턴스변수에 값을 대입합니다.

 

   변수에 static이 붙은 변수를 "클래스변수" 혹은 "스태틱변수"라고 하고 static이 안붙은 변수를

   "인스턴스변수"라고 합니다. (class와 instance 의 차이는 아시죠? class는 자료형의 템플릿(거푸집)이고 instance는 자료형의 실체 잖아요?)

 

   결론: static이 붙고 안붙는 변수의 차이는 아래 표로 정리를 해보았습니다.

  

   static 키워드가 붙은 변수는 전역(global)으로 값이 사용됩니다.

   static이 붙는 변수  static이 붙는 변수
 전역여부

전역변수

X

전역이 아님, 인스턴스변수

 직접대입가능

 O

Human.population 처럼

다이렉트 Access가 가능합니다.

 X

Human aMan = new Human();

aMan.age=10;

static이 안붙는 변수를 사용하기 위해 반드시 new를 사용하여 클래스의 인스턴스를 먼저 만들어야지만 사용이 가능합니다.

 

 private,public과의 관계

 관계는 없지만

주로 public이 사용됨.

public static int a;

이런식으로 주로 public이 static앞에 붙습니다.

왜냐하면 static변수는 주로 전역으로 사용되기 때문이죠.

 - 굳이 private사용하기 사례

 private static int m_age;

 public static int getAge()

{

   return m_age;

}

public static int setAge(int v)

{

   m_age = v;

}

 m_age변수는 private를 사용하여 감추고

 getAge나 setAge는 public을 사용하여 외부에 노출하였습니다.

 - 관계없음.

 

 

 머라고 부르나?  클래스변수

 인스턴스변수=속성=멤버변수

 

cf. 그럼 지역변수(로컬변수)는 먼가?

{}[단위블럭]안에서 생명주기를 가지는 변수를 지역변수라고 합니다.

static Method의 {}안에서 선언된 변수변수는 별개의 thread에 의해 동시에 진입되더라도 독립된 메모리영역에서 생성되어진 값으로 사용됩니다. 즉

static Methoid의 {}안의 선언된 변수와

static 아 아닌 Method의{} 안의 선언된 변수는 똑같이 local variable입니다.

 

 메모리공간

 1개

 해당자료형의크기만큼자리

잡힙니다.

 n개

 - new로 생성된 수만큼 확보

 - 선언된시점의 {}[중괄호블럭]안에서 유효하며 {}바깥에서는 메모리에서 적절히 소멸됨.

 



 

   2. static이 붙고 안붙은 method사례:

    

 아래 class참고

      

public class Human{

    pulbic static long population;/*인구수 static이 붙었습니다.*/

    public int age;/*나이 static이 안붙었습니다.*/

    

    static

   {

       population = 7000000000L;//static블럭안에서 static변수의 값을 초기화 할 수도 있습니다.

   }

 

    public static void addPopulation(long val)

    {

         population += val;

         //age = 3;//<-- static Method안에서 인스턴스변수의 값을 access 하는 것은 불가능합니다.

         //System.out.println(this.hashCode());//<--static Method안에서 this를 access할 수 없습니다.

        // this가 클래스의 인스턴스기 때문이죠.

    }

 

    public void setAge(int val)

   {

      age = val;

      //System.out.println("인류인구:"+Human.population);//static변수는 전역이므로 어디서는 사용가능합니다.

   }

 

}

  

   위와 같은 클래스를 만들어보았습니다.

   2.1  static 키워드가 붙은 함수를 static method[스태틱 메쏘드]라고 합니다.

          static메쏘드는 업무로직이 구현된 함수이며,

          new를 하지 않고 편리하게 사용이 가능합니다.

          - 인스턴스변수를 static함수 내부에 사용할 수 없습니다.

          예) int a = Integer.parseInt("3");//<--- parseInt는 static 메소드이므로 new 없이 사용가능합니다.

    2.2 static 키워드가 안붙은 함수는 instance함수라고 하는데

          get이 붙은 함수는 getter[겟터], set이 앞에 붙은 함수는 setter[셋터]라고 합니다. 

          위의 예시에서 setAge는 age라고 하는 인스턴스의 속성의 값에

          특정한 값을 셋팅하는 setter 입니다.

          - new를 한 후 사용할 수 있습니다.

          - 인스턴스변수를 매개변수로 전달하지 않고 사용할 수 있습니다.

              this.인스턴스변수명 으로 함수내부에서 사용이 가능합니다. this.은 생략 가능합니다.

 

3. 관련 디자인패턴:

    singleton:

    만약 인스턴스를 static방법으로 Access하고자하는 경우

    싱글톤디자인패턴으로 개발하면 되겠습니다.

    싱글톤디자인 패턴은 위에서 설명한 메모리공간에 static은 1개만 들어가는 특징이 있는데

    인스턴스도 1개만 만들어서 static변수에 대입하여 사용하는 디자인 패턴입니다.

 

4. 개발시 유의사항: static변수를 다루는데 있어서 쓰레드 구현시 유의사항이 있습니다.

    앞에서 static변수는 전역변수라고 설명드렸습니다.

    또한 static변수로 선언된 변수는 전역자원(global resource, global data)에 해당됩니다.

    물리적으로 하나의 메모리 공간에 있는 데이터를 처리할 때

    유의해할 것은 동시성 제어를 해야 할 때입니다.

    즉 동시에 한개의 자원(혹은 데이터)을 가져와서

    n개의 쓰레드가 동시에 해당 변수에 접근하였을 때

    값을 읽어와서 쓰려고 하는 과정에서 문제가 생길 수 있습니다.

    전역자원은 배열의 형태일수도 있는데 for문을 돌리는 있는 중간에 다른 쓰레드에 의해서

    배열의 크기가 바뀌거나 할 수 있습니다. 그러면 오류가 생기게 됩니다.

    access오류라든지(가령 ConcurrentModificationException)

    연산오류(정합성체크를 못하는 연산오류) 

    그렇기 때문에 전역자원을 멀티쓰레드(쓰레드는 static자원이 아닙니다.)가 다룰때

    synchronize를 해줘야 하는 경우가 있습니다. 하나의 thread에 의해서만 해당 자원이 다루어

   져야 한다면 synchronize(해당자원){구현...} 이렇게 하면 다음쓰레드는 해당 코드에 동시에

   진입하지 않고 먼저실행된 threa의 {}블럭이 끝날때 까지 기다렸다가 다음쓰레드가 실행되겠습니다.

 

static에 대해 제가 알고 있는 전부라고 해도 과언이 아닙니다.

도움이 되시길 바랍니다.

코드샘플은 제가 이해하시기 좋을 것같은 예로 제가 직접작성하였지만 실제로 돌려보지는 않았습니다.

 


Posted by 세모아
,