JAVA

JAVA 인스턴스 멤버와 정적 멤버

별메아리 2023. 2. 9. 12:50
728x90

인스턴스 멤버와 this

인스턴스 멤버란 객체(인스턴트)를 생성한 후 사용할 수 있는 필드와 메소드를 말하는데, 이들을 각각 인스턴트 필드, 인스턴스 메소드라고 부릅니다. 우리가 지금까지 작성한 모든 필드와 메소드는 인스턴스 멤버였습니다. 인스턴스 필드와 메소드는 객체에 소속된 멤버이기 때문에 객체없이는 사용할 수 없습니다.

 

인스턴스 멤버 선언

인스턴스 필드와 메소드를 선언하는 방법은 지금까지와 같습니다.

public class Car{
 // 필드
 int gas;
 // 메소드
 void setSpeed(int speed){...}
 }

gas 필드와 setSpeed ()메소드는 인스턴스 멤버이기 때문에 객체를 생성해하고 참조 변수 myCar또는 yourCar로 접근해야합니다.

Car myCar = new Car();
myCar.gas = 10;
myCar.setSpeed(60);

Car yourCar = new Car();
yourCar.gas = 20;
yourCar.setSpeed(80);

인스턴스 필드 gas는 객체마다 따로 존재하고, 인스턴스 메소드 setSpeed()는 메소드 영역에 저장되고 공유됩니다.

인스턴스 메소드는 객체에 소속되 있지만 메소드는 코드 블록이므로 객체마다 동일한코드를 가지고 있을필요가 없다.

인스턴스라는 용어가 붙은이유는 메모리 블럭 내부에 인스턴스 필드등이 사용되는 경우가 있기 때문 인스턴스필드가 사용되면 메소드 역시 객체없이는 사용할 수 없습니다.

 

this

객체 외부에서 인스턴스 멤버에 접근하기 위해 참조 변수를 사용하는 것과 마찬가지로 객체 내부에서도 인스턴스 멤버에 접근하기 위해 this를 사용할 수 있습니다. 우리가 자신을 '나'라고 가리키듯이 객체는 자신을 this라고 합니다. this는 주로 생성자와 메소드의 매개 변수 이름이 필드와 동일한 경우, 인스턴스 멤버인 필드를 명시하고자 할 때 사용됩니다.

 

다음은 매개변수 model의 값을 필드 model에 저장합니다.

Car(String model) {
this.model;
}
void setModel(String model) {
this.model = model;
}

인스턴스 멤버와 this

package ch06;

public class Car7 {
	//필드
	String model;
	int speed;
	
	// 생성자
	Car7(String model){
		this.model = model;
	}
	
	// 메소드
	void setSpeed(int speed) {
		this.speed = speed;
	}
	
	void run() {
		for(int i=10; i<=50; i+=10) {
			this.setSpeed(i);
			System.out.println(this.model+"가 달립니다.(시속:"+ this.speed+"km/h");
		}
	}
}

인스턴스 멤버와 this

package ch06;

public class Car7Example {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Car7 myCar = new Car7("포르쉐");
		Car7 yourCar = new Car7("벤츠");
		
		myCar.run();
		yourCar.run();
	}

}

정적 멤버와 static

정적은 '고정된'이란 의미입니다. 정적 멤버는 클래스에 고정된 멤버로서 객체를 생성하지 않고 사용할 수 있는 필드와 메소드를 말합니다. 이들을 각각 정적 필드, 정적 메소드라고 부릅니다.

 

정적 멤버선언

정적 필드와 정적 메소드를 선언하려면 필드와 메소드 선언 시 static 키워드를 추가적으로 붙이면 됩니다. 다음은 정적 필드와 정적 메소드를 선언하는 방법을 보여줍니다.

public class 클래스 {

// 정적 필드

static 타입 필드 [= 초기값];



// 정적 메소드

static 리턴 타입 메소드 ( 매개변수선언, ...) {...}

}

정적 필드와 정적 메소드는 클래스에 고정된 멤버이므로 클래스 로더가 클래스(바이트 코드)를 로딩해서 메소드 메모리 영역에 적재할 때 클래스별로 관리됩니다. 따라서 클래스의 로딩이 끝나면 바로 사용할 수 있습니다.

 

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

 

예)

public class Calculator {
String color;                 // 계산기별로 색깔이 다를 수 있습니다.
static double pi = 3.14159;   // 계산기에서 사용하는 파이 값은 동일합니다.

메소드 역시 인스턴트 필드로 선언할 것인가 아니면 정적 필드로 선언할 것인가의 판단 기준이 필요합니다. 인스턴트 필드를 포함한다면 인스턴트 메소드로 선언하고, 포함하지 않는다면 정적 메소드로 선언합니다.

 

정적 멤버 사용

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

클래스.필드;
클래스.메소드( 매개값, ... );

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

public class Calculator{
	static double pi = 3.14159;
    static int plus(int x, int y) {...}
    static int minus(int x, int 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);

하지만 정적 요소는 클래스 이름으로 접근하는 것이 좋습니다.

 

정적 멤버 사용

package ch06;

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

정적 멤버 사용

package ch06;

public class Calculator4Example {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		double result1 = 10 * 10 * Calculator4.pi;
		int result2 = Calculator4.plus(10,5);
		int result3 = Calculator4.minus(10, 5);
		
		System.out.println("result1:" + result1);
		System.out.println("result2:" + result2);
		System.out.println("result3:" + result3);
	}

}

정적 메소드 선언 시 주의할 점

객체가 없어도 실행된다는 특징 때문에 정적 메소드를 선언할 때는 이들 내부에 인스턴트 필드나 인스턴스 메소드를 사용할 수 없습니다. 또한 객체 자신의 참조일 this 키워드도 사용이 불가능합니다.

public class ClassName {
// 인스턴트 필드와 메소드
int field1;
void method1() {...}
// 정적 필드와 메소드
static int field2;
static void method2() {...}

// 정적 메소드 
static void method3() {
this.field1 = 10; // (x)
this.method();    // (x)
field2 = 10;      // (0)
method2();        // (0)
 }
}

정적 메소드에서 인스턴스 멤버를 사용하고 싶다면 다음과 같이 객체를 먼저 생성하고 참조 변수로 접근해야 합니다.

static void method3() {
ClassName obj = new ClassName();
obj.field1 = 10;
obj.method1();
}

main()메소드도 동일한 규칙이 적용됩니다. main() 메소드도 정적 메소드이므로 객체 생성 없이 인스턴스 필드와 인스턴스 메소드를 main()메소드에서 바로 사용할 수 없습니다.

 

정적 메소드 선언 시 주의할 점

package ch06;

public class Car8 {
	int speed;
	
	void run() {
		System.out.println(speed +"으로 달립니다.");
	}
	
	public static void main(String[] args) {
		Car8 myCar = new Car8();
		myCar.speed =60;
		myCar.run();
	}
}
728x90