티스토리 뷰

주의 사항!

  • 이 글은 제가 직접 공부하는 중에 작성되고 있습니다.
  • 따라서 제가 이해하는 그대로의 내용이 포함됩니다.
  • 따라서 이 글은 사실과는 다른 내용이 포함될 수 있습니다.


정적(static)은 '고정된'이란 의미를 가지고 있습니다. 정적 멤버는 클래스에 고정된 멤버로서 객체를 생성하지 않고 사용할 수 있는 필드와 메서드를 말합니다. 이들을 각각 정적 필드, 정적 메서드라고 합니다. 정적 멤버는 객체(인스턴스)에 소속된 멤버가 아니라 클래스에 소속된 멤버이기 때문에 클래스 멤버라고도 합니다.

 

정적 멤버 선언

정적 필드와 정적 메서드를 선언하기 위해서는 static 키워드를 추가적으로 붙입니다. 다음은 정적 필드와 정적 메서드를 선언하는 예입니다.

public class Car
{
	static int speed;
	static void getSpeed()
	{
		return speed;
	}
}

정적 필드와 정적 메서드는 클래스의 로딩이 끝나면 바로 사용할 수 있습니다.

 

필드를 선언할 때 인스턴스 필드를 선언할 것인가, 아니면 정적 필드로 선언할 것인가의 판단 기준은 객체마다 가지고 있어야 할 데이터라면 인스턴스 필드로 선언하고, 객체마다 가지고 있을 필요성이 없는 공용적인 데이터라면 정적 필드로 선언하는 것이 좋습니다.

 

예를 들어 Calculator 클래스에서 원의 넓이나 둘레를 구할 때 필요한 파이(pi)는 Calculator 객체마다 가지고 있을 필요가 없는 변하지 않는 공용적인 데이터이므로 정적 필드로 선언하는 것이 좋습니다.

public class Calculator
{
	String color;
	static double pi = 3.1415926535;
}

 

메서드의 경우, 인스턴스 필드를 이용해서 실행해야 한다면 인스턴스 메서드로 선언하고, 인스턴스 필드를 이용하지 않는다면 정적 메서드로 선언합니다. 예를 들어 Calculator 클래스의 덧셈, 뺄셈 기능은 인스턴스 필드를 이용하기보다는 외부에서 주어진 매개 값들을 가지고 덧셈과 뺄셈을 수행하므로 정적 메서드로 선언하는 것이 좋습니다.

public class Calculator
{
	String color;
	static double pi = 3.1415926535;
	void setColor(String color) {this.color = color;}
	static int plus(int x, int y) {return x + y;}
	static int minus(int x, int y) {return x - y;}
}

 

정적 멤버 사용

클래스가 메모리로 로딩되면 정적 멤버를 바로 사용할 수 있는데, 클래스 이름과 함께 도트(.) 연산자로 접근합니다.

ClassName.field;
ClassName.method();

예를 들어 Calculator 클래스가 다음과 같이 정의되었다면,

public class Calculator
{
	static double pi = 3.1415926535;
	static int plus(int x, int y) {return x + y;}
	static int minus(int x, int y) {return x - y;}
}

정적 필드 pi와 정적 메서드 plus(), minus()는 다음과 같이 사용할 수 있습니다.

double result1 = 10 * 10 * Calculator.pi;
int result2 = Calculator.plus(10, 5);
int result3 = Calculator.minus(10, 5);

정적 필드와 정적 메서드는 다음과 같이 객체 참조 변수로도 접근이 가능하지만,

Calculator myCalcu = new Calculator();
double result1 = 10 * 10 * myCalcu.pi;
int result2 = myCalcu.plus(10, 5);
int result3 = myCalcu.minus(10, 5);

원칙적으로는 클래스 이름으로 접근해야 합니다. 이클립스에서는 정적 멤버를 클래스 이름으로 접근하지 않고 객체 참조 변수로 접근했을 경우 경고 표시가 나타납니다.

 

정적 초기화 블록

정적 필드는 다음과 같이 필드 선언과 동시에 초기값을 주는 것이 보통입니다.

static double pi = 3.1415926535;

그러나 계산이 필요한 초기화 작업이 있을 수 있습니다. 인스턴스 필드는 생성자에서 초기화하지만, 생성자는 객체 생성 시에만 실행되고, 정적 필드는 객체를 생성하지 않아도 사용할 수 있어야 하므로 생성자에서 초기화 작업을 할 수는 없습니다. 이에 자바는 정적 필드의 복잡한 초기화 작업을 위해서 '정적 블록(static block)'을 제공합니다.

static
{
	...
}

정적 블록은 클래스가 메모리로 로딩될 때 자동적으로 실행됩니다. 정적 블록은 클래스 내부에 여러 개가 선언되어도 상관없습니다. 클래스가 메모리로 로딩될 때 선언된 순서대로 실행됩니다. 다음은 정적 블록을 사용해서 정적 필드를 초기화하는 예입니다.

//Car.java
package chapter00.exam00;

public class Car 
{
	static String company = "현대자동차";
	static String model = "그랜저";
	static String info;
	
	static
	{
		info = company + "-" + model;
	}
}
//exam00.java
package chapter00.exam00;

public class exam00 
{
	public static void main(String[] args)
	{
		System.out.println(Car.info);
	}
}

/*
실행결과

현대자동차-그랜저

*/

 

정적 메서드와 정적 블록 선언 시 주의할 점

정적 메서드와 정적 블록을 선언할 때 주의할 점은 객체가 없어도 실행된다는 특징 때문에, 이들 내부에서는 인스턴스 필드나 인스턴스 메서드를 사용할 수 없다는 것입니다. 또한 객체 자신을 참조하는 this 키워드도 사용할 수 없습니다.

 

main() 메서드도 동일한 규칙이 적용됩니다. main() 메서드도 정적(static) 메서드이므로 객체 생성 없이 인스턴스 필드와 인스턴스 메서드를 main() 메서드에서 바로 사용할 수 없습니다. 따라서 다음은 잘못 코딩된 것입니다.

public class Car
{
	int speed;
	void run() { ... }
    
	public static void main(String[] args)    
	{
		//main() 메서드도 정적(static) 메서드이므로
		//인스턴스 멤버들을 사용할 수 없음
		speed = 60;    //컴파일 에러
		run();         //컴파일 에러
	}
}

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함