Static
static 변수나 메서드의 경우 프로그램 시작과 동시에 메모리에 크기가 할당된다. 그리고 프로그램이 종료할 때까지 할당된 메모리는 사라지지 않는다.
일반적으로 우리가 만든 class는 static 영역에 소속된다. 그 클래스를 new 연산을 통해 객체를 생성할 시 Heap영역에 메모리가 할당된다.
1
2
Scanner sc = new Scnner(System.in);
[static(class) 영역] [Heap 영역]
객체의 생성 시 할당된 메모리는 gc(Garbage Collector)에 의해 관리된다. 그에 반해 Static 키워드를 통해 static 영역에 할당된 메모리는 모든 객체가 공유하는 메모리 라는 강점이 있지만, 프로그램이 끝날 때까지 메모리가 사라지지 않으므로 자주 사용 시 프로그램 성능에 악영향을 미칠 수 있다.
Static 변수의 특징
static 변수는 클래스 변수
객체를 생성하지 않고도 static 자원에 접근 가능
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
public class Calculator { public static add(int x, int y) { return x + y; } public int min(int x, int y) { return x - y; } } public static void main(String[] args) { Calculator.add(1, 2); //static 으로 작성한 메서드라 실행 가능 Calculator.min(1, 2); //static 이 아닌 메서드라 실행 불가능 // min 메서드를 동작하게 하려면 new로 객체를 생성해야 됨 Calculator cl = new Calculator(); cl.min(1, 2); // new 연산으로 객체를 생성해 실행 가능 cd.add(1, 2); // static 메서드 또한 실행 가능 but 권장 X }
Static 변수 (정적 변수)
메모리에 고정적으로 할당되며, 프로그램이 종료될 때 해제되는 변수
왜 우리는 static 변수를 사용할까? 프로그램이 종료될 때까지 해제가 되지 않는다면 그건 메모리 낭비가 아닌가??
처음 static에 대해 배웠을 때 처음 든 생각이다. 하지만 이 static을 제대로 된 방법으로 사용한다면 메모리를 효율적으로 사용할 수 있다.
예를 들어, 세상에 모든 사람의 이름이 sunjong 이라고 치자. 그렇다면 우리는 하나의 객체를 만들어 개인 정보 입력하는 모든 경우에 사용할 수 있다.
1
2
3
4
5
6
7
public class name {
public static final NAME = "sunjong" ;
public static void printName() {
System.out.println(this.NAME);
}
}
만약, 100명의 이름을 출력 해야할 때 static이 아닌 new 연산을 통해 할당하고 출력해야 한다면, 한번 할당한 후 계속 사용 가능한 static에 비해 100배 많은 메모리를 낭비하는 것이 된다. 그래서 일반적으로 static 변수 앞에는 final(상수)가 붙는다.
Static 메소드 (정적 메소드)
static 메소드는 객체의 생성 없이 호출이 가능, 객체에서는 호출이 가능하지만 지양한다.
일반적으로는 유틸리티 관련 함수 같은, 여러번 사용하는 함수의 경우 static 메소드로 구현하는 것이 적합하다. 대표적으로는 java.util.Math가 있다.
1
2
3
4
5
public class math {
public static void printMax(int x, int y) {
System.out.println(Math.max(x,y)); //static 메소드로 선언된 max 함수의 경우 초기화 없이 사용 가능
}
}
또한 static 메소드에서는 static으로 선언되지 않은 변수는 접근이 불가능하다. 그 이유는 메모리 할당과 연관 지어 생각하면 당연하다.
static 메소드의 경우 객체의 생성 없이 접근하는 함수이므로, 할당되지 않은 인스턴스 변수에는 접근이 불가능하다.
1
2
3
4
5
6
7
8
9
public class name {
public String name1 = "sun";
public static String name2 = "jong";
public static void printName() {
System.out.println(name1); // static 변수 아니라 실행 불가능
System.out.println(name2); // 가능
}
}
실제 활용
static 변수
일반적으로 상수들만 모아서 사용한다. 또한 상속을 방지하기 위해 final class로 선언한다.
1 2 3 4 5
public final class AppConstants { public static final String APP_NAME = "MyApp"; public static final String PREF_NAME = "MyPref"; }
static 메소드
마찬가지로 상속을 방지하기 위해 final class로 선언하고, 유틸 관련된 함수들을 모아둔다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
import java.text.SimpleDateFormat; import java.util.Date; import android.util.Patterns; public final class CommonUtils { public static String getCurrentDate() { Date date = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMdd"); return dateFormat.format(date); } public static boolean isEmailValid(String email) { return Patterns.EMAIL_ADDRESS.matcher(email).matches(); } }
Static를 사용할 때 고려할 것들
먼저 클래스의 멤버변수 중 모든 인스턴스에 공통된 값을 유지해야하는 것이 있는지 살펴보고 있으면, static을 붙여준다.
작성한 메서드 중에서 인스턴스 변수를 사용하지 않는 메서드에 대해서 static을 붙일 것을 고려한다.
출처)