[Java 12] 자바 - 클래스 멤버와 인스턴스 멤버

학습목표

  1. 멤버에 대해 정확하게 이해하고 차이점을 파악했다.
  2. 클래스 변수와 메소드의 용도를 알고 제대로 사용이 가능하다.
  3. 멤버 타입 비교의 2가지 원칙을 이해했다.

멤버(Member)란?

멤버

클래스 진도를 나가며 객체를 만들기 위해서 우선 클래스를 정의하고, 클래스에 대한 인스턴스를 만들었습니다. 우리가 만든 객체는 ‘변수(Variable)와 메소드(Method)를 구성원으로 가지게 됩니다. 코드를 통해 알아보기 전, 클래스 멤버와 인스턴스 멤버의 가장 핵심적인 개념 2가지를 기억해야 합니다.

1. 클래스의 멤버는 모든 인스턴스에서 ‘동일’하다.
2. 인스턴스를 생성하지 않아도 클래스에 직접 접근해 사용이 가능하다.

클래스 변수

변수를 선언할 때 인스턴스 변수로 선언할 것인가, 클래스 변수로 선언할 것인가는 각각의 객체마다 개별적인 속성을 가져야할 때는 인스턴스 변수로 선언하고 모든 객체가 공통적인 속성을 가질 때는 클래스 변수로 선언해 사용합니다.

클래스 변수의 용도

1. 인스턴스에 따라서 변하지 않는 값이 필요한 경우
2. 인스턴스를 생성할 필요가 없는 값을 클래스에 저장하고 싶은 경우
3. 값의 변경 사항을 모든 인스턴스가 공유해야 하는 경우


public class Calculator {
	String price;	// price와 brand는 인스턴스 변수
	String brand;	// 계산기의 가격과 브랜드는 각기 다르다.
	static double PI = 3.141592;	// PI는 클래스 변수, 계산기에 사용되는 파이의 값은 모두 동일하다.
	static int base = 0;	// bases는 클래스 변수, 필요에 따라 이 값을 변경해 다른 값 출력하겠다.
}


예제 1
인스턴스에 따라 변하지 않는 값이 필요한 경우에 대한 예제를 살펴봅니다. 해당 예제의 경우 변하지 않는 값은 원주율인 PI입니다.

class Calculator { 
	static double PI = 3.14; // static double PI는 클래스 변수, 클래스 변수를 모든 인스턴스에서 동일값을 가져오겠다!
	int left, right;	//인스턴스 변수

	public void setOprands(int left, int right) {
		this.left = left; // this.left는 인스턴스 변수 int left / left는 setOprand 메소드의 매개변수 int left
		this.right = right;
	}

	public void sum() {
		System.out.println(this.left + this.right);
	}

	public void avg() {
		System.out.println((this.left + this.right) / 2);
	}
}

public class CalculatorMain {
	public static void main(String[] args) {
		//인스턴스를 통해서 PI 접근
		Calculator c1 = new Calculator();
		System.out.println(c1.PI);		//3.14 출력
		Calculator c2 = new Calculator();
		System.out.println(c2.PI);		//3.14 출력

		//클래스를 통해서 PI 접근
		System.out.println(Calculator.PI);	//3.14 출력
	}
}


예제 2
다음 예제는 값의 변경 사항을 모든 인스턴스가 공유해야 하는 경우에 대한 예제입니다. static int base를 추가해 변경된 값을 모든 인스턴스가 공유하고 있습니다.

class Calculator2 { 
	static int base = 0;	//클래스 변수인 base 추가
	int left, right;

	public void setOprands(int left, int right) {
		this.left = left; 
		this.right = right;
	}

	public void sum() {
		System.out.println(this.left + this.right + base); //덧셈에 base 추가
	}

	public void avg() {
		System.out.println((this.left + this.right + base) / 2); //평균치에 base 추가
	}
}

public class CalculatorMain2 {
	public static void main(String[] args) {
		Calculator2 c1 = new Calculator2();
		c1.setOprands(10, 20);
		c1.sum();	//30출력
		c1.avg();	//15출력

		Calculator2 c2 = new Calculator2();
		c2.setOprands(20, 40);
		c2.sum();	//60출력
		c2.avg();	//30출력

		Calculator.base = 10; // base를 10으로 바꿔주어 인스턴스화(모든 인스턴스에 변경된 값을 공유)
		c1.sum();	//40출력
		c1.avg();	//20출력

		c2.sum();	//70출력
		c2.avg();	//35출력
	}
}


클래스 메소드

예제 2의 Calculaor2에서 인스턴스 변수 left와 right를 이용해서 합계와 평균을 구했습니다. 해당 예제는 인스턴스를 굳이 만들어주지 않고 클래스 메소드를 사용해도 동일한 결과를 얻을 수 있습니다.


예제 3

class Calculator3 {
	static int base = 0;	//클래스 변수 base
	// static을 추가함으로써 sum과 avg는 클래스의 메소드가 된다. 
	public static void sum(int left, int right) {	
		System.out.println(left + right + base);
	}
	public static void avg(int left, int right) {
		System.out.println((left + right + base) / 2);
	}
}

public class CalculatorMain3 {
	public static void main(String[] args) {
		//주목할점 : 인스턴스가 등장하지 않았다. Calculator2.sum은 클래스에 직접 접근
		Calculator3.sum(10, 20, Calculator2.base);	//30출력
		Calculator3.avg(10, 20, Calculator2.base);	//15출력

		Calculator2.base = 10;	//클래스 변수 base를 10으로 바꿔준다.
		Calculator3.sum(20, 40, Calculator2.base);	//60출력
		Calculator3.avg(20, 40, Calculator2.base);	//30출력
	}
}

클래스 메소드를 사용해 동일한 결과를 출력했지만 불필요한 인스턴스 생성을 막아 중복된 코드를 줄여주었습니다.

멤버 타입의 비교

멤버 타입 비교

위의 그림처럼 객체는 설계도인 클래스가 먼저 생성되고 그에 따른 인스턴스가 순서대로 생성되게 됩니다. 즉, 인스턴스 변수는 인스턴스가 만들어지면서 생성되는데, 클래스 메소드는 인스턴스 생성되기 전에 만들어지게 됩니다. 따라서 클래스 메소드는 인스턴스 메소드에 접근할 수 없습니다.

1. 인스턴스 메소드는 클래스 멤버에 접근할 수 없다.
2. 클래스 메소드는 인스턴스 멤버에 접근할 수 없다.

멤버 타입 비교

이 두가지 원칙을 기반으로 클래스 멤버와 인스턴스 멤버의 차이점은 무엇인지 생각하고 코드를 작성하는 것이 중요합니다.

태그:

카테고리:

업데이트:

댓글남기기