JAVA 기초4 - 스태틱(static)
스태틱(static)
: static 키워드는 스태틱 멤버 변수(static Member Variable)의 개념을 논하지 않고서는 설명이 불가능하다. 예를 들어보자. 6개의 멤버 변수를 가지고 있는 클래스가 있다고 가정하고, new 연산자를 이용해서 10개의 객체를 생성한다면 내부의 멤버 6개가 한 세트씩 10세트가 만들어진다.
하지만 멤버 필드 중에 static 키워드를 달고 있는 놈이 하나 있다면 전체 멤버 6개 중에서 5개는 하나의 묶음으로 만들어지며 static이 붙어 있는 스태틱 멤버 변수는 생성된 모든 객체들이 공유하는 형식을 사용한다.
Ex)
/*
static 멤버 필드를 테스트하는 예제
*/
public class StaticConcept {
//static 멤버 변수 s는 하나의 메모리만 생성하기 때문에
//어느 곳에서 값을 바꾸든 하나의 메모리를 상대하는 것이 된다.
public static int s; //스태틱 멤버 변수 선언
public int a;
public int b;
public int c;
public int d;
public int e;
public static void main(String[] args) {
StaticConcept st1 = new StaticConcept();
StaticConcept st2 = new StaticConcept();
StaticConcept st3 = new StaticConcept();
//멤버 변수에 데이터 할당
st1.s = 1; st1.a = 1; st1.b = 2; st1.c = 3;
st1.d = 4; st1.e = 5;
st2.s = 10; st2.a = 10; st2.b = 20; st2.c = 30;
st2.d = 40; st2.e = 50;
st3.s = 100; st3.a = 100; st3.b = 200; st3.c = 300;
st3.d = 400; st3.e = 500;
//멤버 변수의 데이터 출력
System.out.println("st1:" + st1.s + ", " + st1.a + ", " + st1.b);
System.out.println(", " + st1.c + ", " + st1.d + ", " + st1.e);
System.out.println("st2:" + st2.s + ", " + st2.a + ", " + st2.b);
System.out.println(", " + st2.c + ", " + st2.d + ", " + st2.e);
System.out.println("st3:" + st3.s + ", " + st3.a + ", " + st3.b);
System.out.println(", " + st3.c + ", " + st3.d + ", " + st3.e);
}
}
: 위의 예제에서 StaticConcept형의 객체 3개를 생성한 후 각각의 멤버에 값을 할당하지만 스태틱멤버는 값이 전부 똑같다. 일반 멤버 변수의 메모리는 따로 생성되지만 스태틱 멤버 변수의 메모리는 하나만 생성된 후 공유하기 때문에 변수 s의 값이 모든 객체에서 동일하게 출력되는 것이다.
결론 적으로 보면 하나의 메모리를 3개의 객체가 공유하고 있는 것이다. 공유 메모리의 성격을 띄고 있음을 알수 있다.
/*
* 스태틱 멤버 변수를 테스트하는 예제
*/
public class HelloCount {
//sCount의 값은 단한번만 초기화
private static int sCount = 0;
//nCount의 값은 객체를 생성할 때마다 초기화
private int nCount = 0;
public void sayHello(){
sCount = sCount + 1;
nCount = nCount + 1;
System.out.println("전체:" + sCount + "번재 인사를 합니다. hello!");
System.out.println(this + "는 " + nCount + "번재 인사를 합니다. Hi!");
}
public static void main(String[] args){
HelloCount h1 = new HelloCount();
HelloCount h2 = new HelloCount();
//h1은 2번 인사
System.out.println(h1 + "의 인사");
h1.sayHello();
h1.sayHello();
System.out.println(); //단순히 다음 라인으로 보내기 위해서 호출
//h2는 3번 인사
System.out.println(h2 + "의 인사");
h2.sayHello();
h2.sayHello();
h2.sayHello();
//전체는 5번 인사
}
}
일반 멤버변수는 객체가 생성될 때마다 메모리가 생성되며, 생성되자마자 0으로 초기화 된다. 그렇기 때문에 객체 자신의 sayHello()를 호출할 횟수를 알 수 없다. 이에 반해 스태틱 멤버는 메모리가 하나만 생성되기 때문에 전체 sayHello()가 몇 번 호출되는지 알 수 있다.
static 멤버변수는 클래스 내에 있는 멤버이다. 그리고 static 멤버도 private과 public의 법칙은 완변하게 지킨다. 메모리가 하나만 생성되고 전체가 공유하는 공유 메모리라고 해서 스태틱멤버에 마음대로 접근할 수 있는 것은 아니다. private static 멤버인 경우에는 public 메소드를 통해서만 접근할 수 있다.
public class StaticTime {
public static int special = 2000;
public static void main(String[] args){
System.out.println("객체 생성 전 접근 - StaticTime.special:");
//객체생성이전에 클래스 이름으로 스태틱에 접근할 수 있다.
System.out.println(StaticTime.special);
//객체의 이름을 이용해서 스태틱에 접급할 수있다.
StaticTime s = new StaticTime();
s.special = 4000;
System.out.println("객체 생성 후 접근- s.special:" + s.special);
System.out.println("객체 생성 후 접근 - StaticTime.special:");
System.out.println(StaticTime.special);
}
}
객체를 생성하기 전에 클래스이름으로 접근한다는 사실은 객체를 생성하기도 전에 이미 메모리가 만들어져 있다는 것을 말해준다.
/*
* 스태틱 멤버 메서드에서 일반 멤버 변수를 사용하는 예(에러)
*/
public class StaticErr {
private int s;
//스태틱 멤버 메서드에서 일반 멤버 변수 사용(애러)
public static void printStaticData(){
//System.out.println(s); //에러
}
public static void main(String[] args){
StaticErr.printStaticData();
}
}
위의 예제에서는 스태틱 멤버 메서드 printStaticData()라는 메소드에서 일반 멤버 변수 s를 사용했기 때문에 컴파일조차 못하고 있다.
위의 일반변수를 static으로 수정하면 컴파일이 될것이다.
- ‘스태틱은 스태틱끼리 동작한다.’라고 생각하면 된다. 당연히 메모리가 생성되기도 전에 스태틱메서드를 호출할 수 잇기 때문에 메모리가 생성되지도 않은 일반 멤버변수를 스태틱 메서드에서 사용할 수 없는 것이다.
2020/11/11 - [개발/자바] - JAVA 기초3 - 접근제어