정적은 영어로 static이라 하고 '고정된' 이라는 의미를 가지고 있다. 정적 멤버라는 것은 클래스에 고정된 멤버라는 것이다.
정적 멤버는 객체를 생성하지 않고 사용할 수 있는 필드와 메소드를 말한다. 그렇기 때문에 객체 즉, 인스턴스에 소속된 멤버가 아니라 클래스에 소속된 멤버이다. 이로 인해 클래스 멤버라고도 한다.
정적 멤버 선언하기
정적 멤버에는 정적 메소드 정적 필드가 있다. 정적 멤버를 선언 할때 static 키워드를 추가적으로 붙여 정적 멤버를 선언할 수 있다.
public class Main{
static int fieldEX = 0;//정적 필드 선언
static void methodEX() { }// 정적 메소드 선언
}
정적 멤버는 Heap영역이 아닌 Static영역에 할당된다. Static 영역에 할당된 메모리는 모든 객체가 공유하여 하나의 멤버를 어디서든지 참조할 수 있는 장점을 가지지만 Garbage Collector의 관리 영역 밖에 존재하기에 Static영역에 있는 멤버들은 프로그램의 종료시까지 메모리가 할당된 채로 존재하게 된다.
Heap영역이나 Garbage Collector에 대해 모른다면 다음을 참고하자.(https://cl0clam.tistory.com/24)
Static영역에 할당된 메모리를 모든 객체가 공유하기 때문에 객체마다 가지고 있을 필요성이 없는 공용적인 데이터라면 정적 필드로 선언하면 좋다. 하지만 너무 정적 필드를 남발하지는 말자.
예를 들어 원의 넓이나 둘레를 구할 때 사용 되는 파이 값은 어느 계산기에서 사용하나 객체마다 가지고 있을 필요가 없는 변하지 않는 공용적인 데이터로 사용 가능하다. 하지만 계산기의 폰트사이즈는 객체 마다 사이즈가 다를 수 있으므로 인스턴스 필드로 선언해야 할 것이다.
public class Calculator{
int Fontsize; //계산기의 폰트사이즈는 다를 수 있지만
static double pi = 3.141592; // 계산기에서 사용되는 파이값은 고유하다.
}
메소드의 경우 어느 경우에 인스턴스 메소드로 선언하고 어느 경우에 정적 메소드로 선언해야 할까. 판단 기준은 인스턴스 필드를 활용하느냐로 나눌 수 있다. 계산기의 폰트 사이즈를 변경하는 메소드의 경우 인스턴스 필드를 사용하게 된다. 따라서 인스턴스 메소드를 사용해야 한다. 하지만 사칙 연산의 경우 외부에서 주어진 매개값들을 가지고 하는 것이기 때문에 정적 메소드가 좋다.
public class Calculator{
String Fontsize;//인스턴스 필드
void setFontsize(String Fontsize) { this.Fontsize = Fontsize; }//인스턴스 필드를 활용한 인스턴스 메소드
static int plus(int a, int b) { return a + b; }//외부에서 두 값을 받아 더하는 정적 메소드
}
정적 멤버 사용하기
정적 멤버는 다음과 같이 .
연산으로 접근한다.
클래스.필드;
클래스.메소드(매개 값, ... );
예를 들어 정적 필드와 정적 메소드를 다음과 같이 사용할 수 있다.
public class Calculator{
static double pi = 3.141592;
String Fontsize = 10;
void setFontsize(String Fontsize) { this.Fontsize = Fontsize; }
static int plus(int a, int b) { return a + b; }
}
double Circle = 2 * 2 * Calculator.pi;
int result1 = Calculator.plus(10, 20);
//다음과 같이 객체 참조 변수로도 접근 가능하다. 하지만 원칙적으로는 클래스이름으로 접근해야된다.
//따라서 되도록 클래스 이름으로 접근하자.
Calculator calEx = new Calculator();
int result2 = calEx.plus(10, 30);
정적 블록
정적 필드는 static int num = 1;
과 같이 선언과 동시에 초기화 하는 것이 일반적이다. 하지만 계산이 필요한 초기화 작업이 있는 경우가 발생 할 수 있다. 정적 필드는 인스턴스 필드처럼 따로 생성자를 활용해 초기화 할 수 없기 때문에 정적 필드의 초기화 작업을 위해 자바는 정적 블록을 제공하고 있다. 정적 블록의 형태는 다음과 같다.
static {
...
}
정적 블록은 클래스가 메모리로 로딩 될 떄 자동으로 실행된다. 클래스 내부에 정적 블록은 여러 개 선언 될 수 있다. 이 때 선언 된 순서대로 정적 블록이 실행된다. 다음 코드를 참고해보자.
public class Tv {
static String company = "LG";
static String model = "OLED";
static String info; //초기화가 되어 있지 않음.
static {//정적 블록
info = company + "-" + model; //info가 LG-OLED로 초기화 된다.
}
}
정적 멤버 주의사항
- 객체가 없어도 실행되기 때문에 객체 자신 참조인 this 키워드 사용이 불가하다.
- 정적 블록 내에서 인스턴스 필드를 초기화 하는 것은 안된다.
main() 또한 정적 메소드로, 객체 생성 없이 인스턴스 필드와 메소드를 바로 사용할 수 없다. 반드시 객체를 생성 한 후 생성해야 한다.
public class Car{
int speed;
void run() { System.out.println("run"); }
public static void main(String[] args) {
//객체 생성을 안하고 초기화하면 안된다.
//speed = 60;
//run();
//다음과 같이 객체를 생성하고 초기화 해야 한다.
Car myCar = new Car();
myCar.speed = 50;
myCar.run();
}
}
'Java' 카테고리의 다른 글
[JAVA] 패키지(package), import문 (0) | 2021.05.06 |
---|---|
[JAVA]final 키워드와 상수(static final)의 이해 (0) | 2021.05.06 |
[JAVA]싱글톤(Singleton)과 getInstance()메소드 (0) | 2021.05.06 |
[JAVA]JVM이 사용하는 메모리 영역(Runtime Data Area) (0) | 2021.05.05 |
[Java] JVM에 대한 이해와 설치 (0) | 2021.05.05 |