보통 고정된 상수값을 static으로 지정하고 사용하다보니...
상세한 내용을 모르고 당연스럽게 쓰고 있었다😂
개념을 정리할 겸 static이 뭐고, 어떻게 쓰는 지 정리해보려고 한다!
보통 Java에서 Static을 사용하면 메모리에 한 번 할당이 된 뒤로는 종료 시에 해제가 된다.
런타임에서 실행되는 게 아니라는 소리다!
일반적으로 Class는 Static 영역에, new 연산을 통한 객체는 Heap 영역에 생성이 된다.
Heap 영역의 메모리는 Garbage Collector를 통해 수시로 관리를 받게 되지만,
Static 에 할당이 되면 모든 객체가 공유하는 메모리로 관리 영역 밖에 존재한다.
단순히 보면 고정시켜 놓은 값이라고 할 수 있는데,
자주 또는 많이 사용하게 되면 프로그램 종료 시까지 메모리 영역에 존재하게 되어 악영향을 끼칠 수 있다!
Instance 사용의 장점
- 동적인 값으로 static과 달리 재사용하기 좋다.
- Instance 객체를 개수 제한없이 분리하여 사용할 수 있다.
Instance 사용의 단점- 인스턴스 객체는 new로 그때마다 생성하므로 리소스를 많이 잡아먹게 된다.
단순히 정적인 요소에 부여한다고만 알고 있었는데...
그럼 실제로 어떻게 사용하는지 보고자 한다!🤔
class Box {
/* 인스턴스 변수 (개별 속성) */
public String kind; // 박스 종류
public int cnt; // 박스 수량
/* 클래스 변수 (공통 속성) */
public static int width = 200;
public static int height = 500;
}
class Main {
public static void main(String args[]) {
// static 변수 호출
System.out.println(Box.width); // 결과 : 200
// 객체 생성
Box box = new Box();
box.kind = "wood";
// 인스턴스 변수 호출
System.out.println(box.kind); // 결과 : wood
}
}
위와 같은 경우로 예를 들면,
공통적으로 동일하게 사용하는 속성은 정적인 면이 있으므로 static 변수로 사용한다.
그와 달리 종류나 수량처럼 속성이 변하는 요소는 인스턴스 변수로 사용을 한다.
박스를 제조하는 업체가 가로, 세로는 동일한 상태에서
종류나 수량의 옵션만 추가로 주문을 받는 식이라고 보면 된다!
가로, 세로까지 인스턴스 변수로 놓는 경우, 값은 누가 주문하든 동일한데...
주문내역에 해당 값이 항상 같이 프린트 되어진다고 보면 된다.
그래서 오히려 주문내역을 보기 힘들고 길어지게 만드는 요소이기에 고정 값인 변수는 static으로 분리시킨다고 볼 수 있다.
(public이나 private은 변수를 사용하는 위치에 따라 설정해주면 된다...)
🚨 그리고 static 변수는 static 메서드에서 사용하는 걸 권장!
물론 static 변수도 객체로 생성된 box.width로 가져다 쓸 수는 있지만...
이는 권장되는 방법이 아니다!
Class 객체인만큼 Class.객체명으로 사용하는 것이 좋다!
class StaticOrInstance {
void instanceMethod() {}
static staticMethod() {}
void instanceMethodCall() {
instanceMethod();
staticMethod();
}
static void staticMethodCall() {
instanceMethod(); // X
staticMethod();
}
}
위처럼 작성한 메서드를 보면 staticMethodCall에서 실행한 instanceMethod()는 에러가 난다.
instanceMethodCall에서는 전부 불러와지는데, 왜 static 메서드는 static 메서드만 실행이 될까??
=> Static은 클래스에 속하고, Instance는 객체에 속하기 때문!
Static 메서드는 클래스 자체에 속하기 때문에 인스턴스 객체를 만들지 않고도 호출이 가능하다.
하지만 인스턴스 메서드는 특정 객체에 속하므로 그 객체를 생성해야만 호출이 가능해진다.
Static 메서드는 클래스 차원에서 작동하기에, 어떤 객체가 만들어졌는지를 모르게 된다.
따라서 객체가 요구되는 인스턴스 메서드 자체를 호출할 수 없게 된다.
위에 객체에서도 언급했듯이 static은 객체 없이 호출이 가능한 것도 이유다.
인스턴스 메서드에서는 객체가 이미 생성된 상태이기에 static도 가능하고 instance도 가능해지지만,
static에서는 객체가 생성되지 않았으므로 클래스 공통 메서드인 static 메서드만 사용이 가능해진다.
class Math {
// 인스턴스 변수
int a, b;
// 인스턴스 메서드
int add() {
return a + b;
}
// static 메서드
static int add(int a, int b) {
return a + b;
}
}
class Main {
public static void main(String args[]) {
// static 메서드 호출
System.out.println(Math.add(100, 200));
// 인스턴스 생성
Math math = new Math();
math.a = 100;
math.b = 200;
// 인스턴스 메서드 호출
System.out.println(math.add());
}
}
이와 같은 방식으로 인스턴스 객체를 생성한 후 그를 통해 객체나 메서드를 이용할 수는 있다!