728x90

이 강의는 자바의 프로젝트를 어떻게 만드는지, 또한 빌드를 어떻게 하는지에 대한 강의를 진행하지 않는다.

그러나 자바의 기본적인, 그리고 자바에 필수적인 기능들도 분명 존재하고 이 블로그엔 그 작업에 필요한 포스팅도 함께 제공하고 있다.

그 정보를 확인하고 싶다면 여기를 참조하라. 양이 조금 되고 현재진행형으로 늘어나고 있으므로 페이지내의 찾기(ctrl+f 나 cmd+f)로 찾아보도록하자.


이제 객체에 대해서 어느정도 배웠다. 지금까지의 방법으로도 사실 사용하는데 큰 문제는 없다.

그러나 객체를 사용하는데 특별한 형식이 필요한 경우도 분명 존재한다.

아래 같은 상황의 예를 들어보자.


public class Circle {
int r;
float pi = 3.14f;

Circle(int r) {
this.r = r;
}

void setPi(float pi) {
this.pi = pi;
}

float getArea() {
return r * r * pi;
}
}


이 같은 클래스가 존재한다고 하자.

이 클래스를 기반으로 아래의 main을 실행해보도록 하자.


public class Main {
public static void main(String[] args) {
Circle c1 = new Circle(5);
Circle c2 = new Circle(7);

System.out.println(c1.getArea());
System.out.println(c2.getArea());

c1.setPi(3);
c2.setPi(3);

System.out.println(c1.getArea());
System.out.println(c2.getArea());
}
}


원주율 pi값은 경우에 따라 바뀔 수 있다.

예를 들어서 수학문제를 쉽게 풀게 배려하기 위해서 원주율을 3으로 바꾼다던가

반대로 물리를 치밀하게 계산하기 위해서 원주율을 3.141592등으로 상세하게 바꾼다던가...


그런데 위 코드의경우 문제점이 있다.

원주율이 각각의 인스턴스 마다 존재하기 떄문에 바꿔주려면 모두 바꿔줘야한다는 것이다.

물론 따로따로 적용하고 싶은 사람도 있겠지만 대부분의 경우에 원주율은 공통되게 사용하고 싶을 것이다.

이런 문제를 해결하려면 어떻게 하면 될까?

그래서 등장한 것이 바로 static이다.

static은 클래스 단위로 공유하게 만드는 지시자라고생각하면 되겠다.


public class Circle {
int r;
static float pi = 3.14f;

Circle(int r) {
this.r = r;
}

void setPi(float pi) {
this.pi = pi;
}

float getArea() {
return r * r * pi;
}
}


Circle의 pi를 static변수로 선언했다. 이제 pi는 모든 Circle클래스들이 공유하게 된다.

이러한 static변수를 같은 클래스가 공유하는 클래스라는 의미에서 클래스변수라고 부르게 된다.


public class Main {
public static void main(String[] args) {
Circle c1 = new Circle(5);
Circle c2 = new Circle(7);

System.out.println(c1.getArea());
System.out.println(c2.getArea());

c1.setPi(3);

System.out.println(c1.getArea());
System.out.println(c2.getArea());
}
}


이제 아까의 main소스를 수정해보자. 아까는 c1과 c2의 배율을 수정하기 위해서 모두 수정하였다.

그러나 이제는 그렇지 않다. 단 하나만 수정해도 둘 모두가 변경되게 된다.

그 이유는 pi가 클래스 변수가 되어서 하나가 쓰는게 아니라 모두가 공유하게 되는 변수가 되었기 때문이다.


그러면 한가지 의문점에 도달하게 된다.

어짜피 c1과 c2상관없이 Circle이라는 클래스는 pi를 공유하게 된다.

그러면 굳이 인스턴스명으로 접근하는게 의미가 있을까?

당연하지만 의미가 없다. 따라서 static변수는 클래스명으로 접근하는게 가능하다.


public class Main {
public static void main(String[] args) {
Circle c1 = new Circle(5);
Circle c2 = new Circle(7);

System.out.println(c1.getArea());
System.out.println(c2.getArea());

Circle.pi = 3;

System.out.println(c1.getArea());
System.out.println(c2.getArea());
}
}


보시다시피 static변수는 클래스명으로 접근할 수 있다.


그러면 static을 메소드에 붙힐 수 없을까?

물론 이 역시 가능하다.

또한 이미 여러분은 static메소드를 뻔질나게 사용하고 있다.

바로 static main이다. 메소드에 static을 붙히면 기존의 클래스변수와 마찬가지로 클래스 메소드와 부르며 특성역시 같다.

클래스 메소드들은 인스턴스 변수를 쓸수없고 static변수만의 사용이 강제된다.

그 이유는 조금만생각해보면 알 수 있으니 설명하지 않겠다.


public class Circle {
int r;
static float pi = 3.14f;

Circle(int r) {
this.r = r;
}

static void setPi(float pi) {
Circle.pi = pi;
}

float getArea() {
return r * r * pi;
}
}


이제 setPi는 클래스메소드로 호출했다. 클래스메소드에서 this라는건 없다.

어짜피 인스턴스단위에서 호출되지 않기 때문이다. 그리고 클래스변수만 호출할 수 있다.

따라서 클래스변수를 호출할때는 클래스명으로 접근을 해야한다.


public class Main {
public static void main(String[] args) {
Circle c1 = new Circle(5);
Circle c2 = new Circle(7);

System.out.println(c1.getArea());
System.out.println(c2.getArea());

Circle.setPi(3);

System.out.println(c1.getArea());
System.out.println(c2.getArea());
}
}


이제 setPi역시 클래스 함수이므로 변수의 이름으로 호출할 수 있다.


static 규칙

1.static 변수나 함수는 클래스명으로 접근할 수 있다. 그러나 클래스명만 사용해야하는건 아니다.

2.static 함수내에서는 static 변수만 사용할 수있다. 물론 일반 지역변수도 사용 가능하다.

3.static 함수 내에서 this의 호출은 불가능하다.


+ Recent posts