Java에서 Static 키워드를 사용한다는 것은 메모리에 한번 할당되어 프로그램이 종료될 때 해제되는 것을 의미합니다. 이를 정확히 이해하기 위해서는 메모리 영역에 대한 이해가 필요합니다.
일반적으로 우리가 만든 Class는 Static 영역에 생성되고, new 연산을 통해 생성한 객체는 Heap영역에 생성됩니다. 객체의 생성시에 할당된 Heap영역의 메모리는 Garbage Collector를 통해 수시로 관리를 받습니다.
하지만 Static 키워드를 통해 Static 영역에 할당된 메모리는 모든 객체가 공유하는 메모리라는 장점을 지니지만, Garbage Collector의 관리 영역 밖에 존재하므로 Static을 자주 사용하면 프로그램의 종료시까지 메모리가 할당된 채로 존재하므로 자주 사용하게 되면 시스템의 퍼포먼스에 악영향을 주게 됩니다.
메모리를 효율적으로 사용이 가능하다. 생성할 때 마다 인스턴스가 힙에 올라가는 것이 아닌 고정 메모리 이므로 보다 효율적이다.
속도가 빠르다. 객체를 생성하지 않고 사용하기 때문에 속도가 빠르다는 이점이 있다.
무분별한 static의 사용은 메모리 유수(Leak)의 원인이 된다. 프로그램 종료 시점에 메모리를 반환하는 속성이 있어 GC(Garbage collection) 대상이 아니기 때문이다.
재 사용성이 떨어진다. 정적인 값이기때문에 interface를 구현하는데 사용될 수 없다.
Static 변수는 클래스 변수입니다. 객체를 생성하지 않고도 Static 자원에 접근이 가능합니다.
public class MyCalculator {
public static appName = "MyCalculator";
public static int add(int x, int y) {
return x + y;
}
public int min(int x, int y) {
return x - y;
}
}
MyCalculator.add(1, 2); // static 메소드 이므로 객체 생성 없이 사용 가능
MyCalculator.min(1, 2); // static 메소드가 아니므로 객체 생성후에 사용가능
MyCalculator cal = new MyCalculator();
cal.add(1, 2); // o 가능은 하지만 권장하지 않는 방법
cal.min(1, 2); // o
Java에서 Static 변수는 메모리에 한번 할당되어 프로그램이 종료될 때 해제되는 변수로, 메모리에 한번 할당되므로 여러 객체가 해당 메모리를 공유하게 됩니다.
public class Person {
private String name = "jaewoo";
public void printName() {
System.out.println(this.name);
}
}
하지만 위와 같은 클래스를 통해 100명의 Person 객체를 생성하면, "jaewoo"라는 같은 값을 갖는 메모리가 100개나 중복해서 생성되게 됩니다. 이러한 경우에 static을 사용하여 여러 객체가 하나의 메모리를 참조하도록 하면 메모리 효율이 더욱 높아질 것입니다.
또한 "jaewoo"라는 이름은 결코 변하지 않는 값이므로 final 키워드를 붙여주며, 일반적으로 static은 상수의 값을 갖는 경우가 많으므로 public으로 선언을 하여 사용합니다.
이러한 이유로, 일반적으로 static 변수는 public 및 final과 함께 사용되어 public static final로 활용 됩니다.
public class Person {
public static final String name = "jaewoo";
public static void printName() {
System.out.println(this.name);
}
}
위의 코드를 보면, printName이라는 함수 역시 static 키워드가 붙어서 static메소드가 되었는데, static 변수는 static 메소드를 통해 접근하도록 권장되기 때문입니다.
cf. 인스턴스(Instance) 메서드란?
인스턴스 객체를 생성 후 "인스턴스변수.메서드()" 형태로 호출하는 방식으로, 인스턴스 멤버와 관련된 작업을 하는 메서드이다. 메서드 내에서 인스턴스 변수를 사용할 수 있다.
class Math1 {
//인스턴스 변수
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(Math1.add(200,100);
//인스턴스 생성
Math1 mt1 = new Math1();
mt1.a = 200;
mt1.b = 100;
//인스턴스 메서드 호출
System.out.println(mt1.add());
}
}
Card라는 클래스를 만들어 예제로 확인해보자.
class Card{
/* 인스턴스 변수 (개별 속성) */
String kind; //카드 종류
int number; //카드 번호
/* 클래스변수 (공통 속성) */
static int width = 150; //폭
static int height = 300; //높이
}
개별 속성을 부여해야 하는 카드 종류와 번호의 변수는 인스턴스 변수로 생성을 하고 클래스 내부에서 공통으로 정해져있는 정적인 값을 사용하는 변수는 static으로 사용했다.
이와 같이 정적으로 사용하는 변수는 static을 사용하면 된다.
마지막으로 메서드를 사용할 때는 어떤지 한번 예제로 확인해보자.
class StaticStudyClass{
void instaceMethod() {} //인스턴스 메서드 생성
static void staticMethod() {} //static 메서드 생성
//인스턴스 메서드
void instanceMethodCall(){
instanceMethod(); //호출 O
staticMethod(); //호출 O
}
//Static 메서드
static void staticMethodCall() {
instanceMethod(); //호출 X (에러 발생 => static메서드는 객체를 생성하지 않기때문에 인스턴스 메서드를 사용할 수 없다.)
staticMethod(); //호출 O
}
}