본문 바로가기

개발일지/Java + Spring

211027 java - 생성자에서 상수 초기화 (5)

 

생성자에서 상수 초기화 

 

final로 정의된 값은 상수 라고 한다. 원래는 초기화 하자마자 값을 세팅해줘야 하지만 여기서는 특이하게 생성자에서 상수 초기화를 해줄 것이다. 이 의미는 메인에서 객체 생성을 할 때 인자에 값을 주게 되면 그 값이 바로 상수가 된다는 것이다. 이 후로는 바꿀 수 없는 값이라고 생각하면 됨

 


일단 코드 훑어 보기

class Card2 //extends Object 생략된 것임
{
	final int NUMBER; //상수는 풀대문자. 
	//final은 원래는 초기화 하자마자 값을 세팅해야함
	//그런데 유일하게 생성자에서 세팅하는 것도 가능하다. 
	final String KIND;
	static int width = 100;
	static int height = 250;
	
	//생성자 오버로딩 
	Card2(String kind, int num)
	{
		KIND = kind;
		NUMBER = num;
	}
	
	Card2()
	{
		this("HEART", 1);
		//매개변수 2개짜리 다시 호출
		//매개변수 없는 경우 이걸 출력
	}
	
	Card2(String kind)
	{
		this(kind, 2);
	}
	
	Card2(int num)
	{
		this("HEART", num);
	}
	
	//오버라이딩
	public String toString()
	//원래는 오브젝트 클래스에 있던 toString임
	//주소값을 찾아 주는 것이었음
	{
		return KIND + "--" + NUMBER;
	}
	
	//오버라이딩을 없애면 test1026.Card2@15db9742 이게 뜬다 주소값 
	/*
	 * public String toString() { }
	 * 오브젝트 메소드를 오버라이딩 하고 싶다면 선언부를 똑같이 해줘야 한다!!
	 */
}

public class Sample1027_3 {
	
	public static void main(String[] args) {
		Card2 c = new Card2("HEART", 10);
		//c.NUMBER = 11; 상수 라서 안 됨 
		
		System.out.println(c.KIND);
		System.out.println(c.NUMBER);
		System.out.println(c); //참조형
		//System.out.println(c.toString());
		//println을 분석하면 인수가 참조형이라서 toString을 알아서 호출을 해준다.
	}
}

 

하나하나 뜯어보기

 

class Card2 //extends Object 생략된 것임
{
	final int NUMBER; 
	final String KIND;
	static int width = 100;
	static int height = 250;

 

모든 클래스에는 Object 클래스 라는 최상단의 클래스를 상속 받고 있다. 그래서 extends Object를 해주지 않아도 클래스 안에 자동으로 포함하고 있다. 

 

final int NUMBER;

final String KIND;

 

final 상수값은 풀대문자를 사용한다. 원래는 초기화를 하자마자 값을 세팅해야 하지만 유일하게 클래스 내부의 생성자에서 세팅하는 것도 가능하다. 

 

static int width = 100;
static int height = 250;

카드의 크기는 다른 카드들도 똑같으니까 static으로 클래스 변수를 지정해준다. 인스턴스 변수는 객체 생성시에만 만들어주는 특징이 있음

 

 

	//생성자 오버로딩 
	Card2(String kind, int num)
	{
		KIND = kind;
		NUMBER = num;
	}

 

생성자 오버로딩

하나의 클래스에서 메소드의 이름이 동일한 경우 매개 변수의 개수와 타입이 다르게 재정의가 가능하다.

 

객체 생성을 할 때 인자값이 2개인 경우 KIND, NUMBER 차례대로 값을 넣어준다. 그럼 객체 생성을 하면서 등록한 값이 상수에 반영이 되는 것임. (대문자는 클래스에서 지정했던 상수값이고, 뒤쪽의 소문자는 파라미터 값으로 받은 것)

 

	Card2()
	{
		this("HEART", 1);
	}

 

 

메인에서 객체생성을 할 때 인자값에 아무것도 넣지 않은 경우 이곳으로 오게 되는데 this()로 다른 생성자를 호출한다. 생성자 오버로딩으로 올라가서 대입하는 것을 갖고 오는 거임. 반드시 첫줄에서 실행이 되어야 함. 데이터 값이 같은 곳 KIND, NUMBER에 이 값이 저장이 됨

 

 


	//오버라이딩
	public String toString()
	//원래는 오브젝트 클래스에 있던 toString임
	//주소값을 찾아 주는 것이었음
	{
		return KIND + "--" + NUMBER;
	}
}

 

이 메소드는 원래 Object 클래스에 있던 toString이라는 메소드이다. 주소값을 찾아주는 예약어지만 여기서는 오버라이딩을 하려고 한다. 오버라이딩을 할 때는 선언부를 똑같이 해줘야 하는데 모를 땐 메인에서 toString에서 컨트롤 클릭을 하면 선언부를 볼 수 있음

 

만약 이 오버라이딩을 없애면? 메인 마지막 출력에서 test1026.Card2@15db9742 이렇게 주소값을 출력한다.

 

public class Sample1027_3 {
	
	public static void main(String[] args) {
		Card2 c = new Card2("HEART", 10);
		//c.NUMBER = 11; 상수 라서 안 됨 
		
		System.out.println(c.KIND);
		System.out.println(c.NUMBER);
		System.out.println(c); //참조형
	}
}

 

객체 생성 뒤에 KIND, NUMBER를 바꾸고 싶어도 상수 라서 값을 바꿀 수 없다. 


System.out.println(c.toString()); 이것을 하지 않고 System.out.println(c); 이렇게 해주는 이유는 c는 참조형 타입이라서 그럼. println을 분석할 경우 인수가 참조형이라서 toString을 알아서 호출하게 돼 있다. 그러니 굳이 뒤에 메소드를 사용하지 않아도 된다.

 

print에 참조변수가 오는 경우 주소값을 원래는 찍어야 되는데 위에 있는 메소드를 사용하게 된다. 왜냐하면 같은 메소드가 있을 때 자식부터 실행을 하고 부모 메소드를 실행하기 때문에~~!

 

 

출력값

HEART
10
HEART--10

 


 

매개변수가 1개만 있을 때는?

 

	Card2(String kind)
	{
		this(kind, 2);
	}
	
	Card2(int num)
	{
		this("HEART", num);
	}

 

매개 변수가 1개일 때는 또 매개변수가 1개인 생성자 2개(kind, num)를 만들어주면 된다.