Wanna be Brilliant Full-Stack Developer

Java 자바 객체지향 프로그래밍 문법 #4 #생성자 본문

Some Memos/Java

Java 자바 객체지향 프로그래밍 문법 #4 #생성자

Flashpacker 2022. 3. 2. 18:24


1) 생성자라는걸 배워보자!

package ch04;

public class Cat {
	String name;
	String color;
}

이렇게 하면 선언만하고 초기화라는것을 안했다

초기화를 안했다는것은 값을 안넣었다는것이다.

왜 초기화 하지 않았는가? 

 

결과는 null이 나온다! 처음 배우는 데이터 타입 데이터이다.. 

Null 자체도 데이터이다. 값이 없음을 의미하는데 heap공간에 머가 들어가있냐면 null이라는 데이터가 들어가 있다.

왜? 초기화 하지 않았기 때문에! 지난번에 Dog할때는 값을 다 초기화를 해놨는데, 

지금은 초기화를 하지 않았다 . 왜 초기화를 하지 않았냐면? 

우리가 고양이를 하나 만들었는데 

이전에서도 강아지를 통해서 강아지를 하나 클래스 d1을 만들었는데? 

하나를 만들떄는 상관없는데 고양이를 여러개 만든다고 생각해보자? 

package ch04;

public class Cat {
	String name = "집사";
	String color ="하얀색";
}

내가 이 Cat이라는 클래스를 통해서 애를 메모리에 띄울때 CatApp에서 실행하면 고양이하나가 만들어졌고

이렇게 이름이 둘다 집사이고 색깔이 하얀색인 고양이를 만들었지만
다른 색상의 다른이름의 고양이를 만들 수 없다. 

그래서 클래스를 만들어서 상태를 정의할때는 값을 초기화 하지 않는다. 

package ch04;

public class Cat {
	String name;
	String color;
}
package ch04;

public class CatApp {

	public static void main(String[] args) {
		Cat c1 = new Cat(); // 고양이 한마리가 힙공간에 만들어짐
		System.out.println(c1.name); // null 자체도 데이터이다. 값이 없음을 의미
		System.out.println(c1.color);
		
		Cat c2 = new Cat(); // 고양이 한마리가 힙공간에 만들어짐
		System.out.println(c2.name);
		System.out.println(c2.color);

	}

}

값은 이렇게 아무것도 안나온다! 

package ch04;

//값을 초기화 하지 않는 이유는 new 할때마다 다른 상태를 가진 고양이를 만들기 위해서이다!!
public class Cat {
String name;
String color;
}

 

조금더 예를 들어 설명해보자!

 

우리가 신이 있는데 신이 사람이라는 클래스(설계도) 를 만들었다 

아직 이사람은 이 세상에 존재하지 않는다. 

여기 우리가 사는 세상이 있다. 

우리가 할것은 이 클래스(사람) 를 잘만들어놨으니까
애를 통해서 사람을 하나씩 이 세상에 뿌리내리고 싶다! 

 

그떄 New를한다 이세상은 Heap세상 이자  메모리 이다. ( 메모리에 띄우기 위해서 new를 한다) 

사람을 new를 했을떄 값이 만약 초기화가 되어있다면 어떻게 될까? 

age = 1 , name = "홍길동" 으로 초기화 되어있다면? 

new할떄마다 태어나는 모든 사람은 또 new를 여러번 신이 할 수 있다.

new를 할때마다 모든 사람들의 이름은 홍길동이다. 나이는 1살, 나이 1살은 문제 없지만 앞에 final로 정의를 안했으니까
이세상에 딱 태어나서 이름을 바꾸면 된다. 이름 변경이 되는데 먼가 불편하다 (태어나서 이름을 변경하는것) 

태어날떄부터 내가 이름을 지어주는것이 좋지 않을까? 

그럴려면 신이 설계도를 만들떄 사람이라는 설계도를 만들고 이떄
애 나이 (age;) , 이름(name) , 키 (height),
몸무게 (weight;)
이런것들에 대해서 초기화를 해버리면 안된다.

왜 안되냐면 초기화를 해버리면 태어날떄부터 모두 똑같은 복제 인간이 태어난다 .

우리는 복제 인간을 원하지 않는다! 

 

만약에 우리가 복제 인간을 원하면 초기화를 해버리면 된다. 하지만 복제인간을 원하지않으면 초기화하지 않는다! 

태어날때마다 다양성을 가지길 원한다! 

여기서 태어날때마다의 의미는 자바프로그램에서는 new를 말한다!

이세상에 뿌리 내려보려고하는데

이세상에 뿌리 내리려고 할떄 이세상은 메모리이다

이 사람을 new할때마다 다양성을 위해서 값을 다르게 해줘야한다! 

태어나고 나서 값을 변경하는게 아니라 태어날떄 다양성을 위해 값을 초기화 해주고싶다면?

그떄 사용하는것이 '생성자' 이다! 

new할때 생성자를 통해서 나이는 1, 이름은 홍길동 키는 50 , 몸무게 5 kg 이렇게 초기화해서

사람을 태어나게 할 수 있다! 

나머지 애들도 태어날떄 각각 머를 통해서 값을 초기화 하는가?
그것은 new할때마다 생성자를 이용해서 
다르게 초기화 할수 있다!  

이거를 초기화 한다! 영어로 하면 initialized  이걸 한번 해보자!

여기서 컨트롤 스페이스를 하면 Constructor가 나온다! 

package ch04;

//값을 초기화 하지 않는 이유는 new 할때마다 다른 상태를 가진 고양이를 만들기 위해서이다!!
public class Cat {
	String name;
	String color;
	
	public Cat() { // 생성자 (메서드) 
		System.out.println("고양이 탄생함");
		
	}
}

생성자의 생김을 보면 public이 붙어있고 클래스이름이랑 똑같은데 ()가 붙어있는데 이게 생성자라고 한다! 

쉽게 말하면 메서드이다. 

new할때 무슨일이 일어났는가? new할때 고양이 탄생함이 실행된다! 

new할때 생성자가 무조건 실행되는것이다! 

 

재밌는것을 해볼껀데! 저 new Cat을 컨트롤로 내부를 들어가면 

이곳으로 이동되고 애를 실행한다! 

new는 메모리에 heap공간에 할당하는것이고
Cat()는 생성자를 호출이다.
그래서 new Cat ()은 메모리에 할당하면서 생성자를 호출하는것인데
new를 할떄 어떠한 어떠한것들이 메모리에 뜨는가? 

Static이 아닌 모든것들이니까 String name, String color 메모리에 띄우고 

그리고 new를 하면서 생성자가 최초에 한번 호출이된다  - > 상태를 초기화 하기 위해서 

거기를 가리키는 c1은 heap공간을 가르키는 주소 

Cat은 커스텀 타입( 개발자 가 만든 타입 )

 

package ch04;

//값을 초기화 하지 않는 이유는 new 할때마다 다른 상태를 가진 고양이를 만들기 위해서이다!!
public class Cat {
	String name;
	String color;
	
	public Cat(String n, String c) { // 생성자 (메서드) 
		System.out.println("고양이 탄생함");
		System.out.println("n : " + n);
		System.out.println("c : " + c);
		
		
	}
}

이렇게 매개변수를 두개를 만들고 저장을 하면 CatApp은 오류가나온다. 

 

package ch04;

//값을 초기화 하지 않는 이유는 new 할때마다 다른 상태를 가진 고양이를 만들기 위해서이다!!
public class Cat {
	String name;
	String color;
	
	// Cat() 생성자를 디폴트 생성자라고 한다.
	// 개발자가 적지 않아도 있는 것!!( 생략 가능한 코드) 
	public Cat() {
		
	}
	
	public Cat(String n, String c) { // 생성자 (메서드) 
		System.out.println("고양이 탄생함");
		System.out.println("n : " + n);
		System.out.println("c : " + c);
		
		
	}
}

하지만 이렇게 Cat() { } 를 생성하면 오류가 사라지는데 이걸 디폴트 생성자라고 부르고 개발자가 적지 않아도
있는것! 생략 가능한 코드인데 

언제 애가 생략이 불가능하냐면 개발자가 직접 생성자를 구현하게 되면 디폴트 생성자가 생략될 수 없다. 

 

내가 직접 구현했다는건 무엇이냐면 내가 밑에다가 생성자를 하나 구현했다 

내가 직접 구현한 생성자가 있다면 디폴트 생성자를 생략하게되면 호출하는 클래스에서 오류가나온다! 

 

Dog를 보면 생성자가 없다. 없는데도 Dog App에서  new Dog() 매개변수가 아무것도 없는 디폴트(기본)생성자를 호출했다

디폴트 생성자를 뭘 이야기하는거냐면 매개변수가 아무것도 없는걸 디폴트 생성자라고 한다. 

Dog에서 생성자를 안만들어도 DogApp에서 호출이 가능하다 왜냐하면 안적어도 만들어준다는것이다. 

매개변수가 없는 생성자는 디폴트(기본) 생성자이다.

편하게 쓰기 위해서 

하지만 내가 디폴트 생성자가 아닌 어떤 생성자를 구현하게되면 기본적으로 없기 떄문에 내가 직접 적어줘야한다! 

여기서 왜 값이 다시 Null이 되냐면 new Cat을 컨트롤 로 내부 들어가면 디폴트 생성자를 가리키기떄문에

디폴트 생성자 말고 매개변수가 있는 생성자를 호출하기 위해서는 매개변수를 넣어주면 된다.

하지만 null인 값들이 있다. 상태 값은 null인데 

우리가 한건 new를 하면서 다양성을 가진 고양이들을 만들 수 있다. 

아직은 완벽하게 만든것은 아니다.  값을 호출할때는 null이 나오기떄문!

package ch04;

//값을 초기화 하지 않는 이유는 new 할때마다 다른 상태를 가진 고양이를 만들기 위해서이다!!
public class Cat {
	String name;
	String color;
	
	// Cat() 생성자를 디폴트(기본) 생성자라고 한다. ( 디폴트 생성자) 
	// 개발자가 적지 않아도 있는 것!!( 생략 가능한 코드) 
	// 내가 직접 생성자를 구현하게 되면 디폴트 생성자가 생략 될수 없다.
	// 개발자가 생략 가능한 코드 
	public Cat() {
		
	}
	
	//개발자가 직접 생성자 구현함 = 디폴트 생성자가 생기지 않음.
	public Cat(String n, String c) { // 생성자 (메서드) 
		System.out.println("고양이 탄생함");
		System.out.println("n : " + n);
		System.out.println("c : " + c);
		
		// String n, String c는 지역변수 = Cat() 이라는 생성자(메서드) 가 가진 변수
		name = n;
		color = c;
	}
}

String n, String c 는 지역변수이다 = Cat() 이라는 생성자(메서드)가 가진 지역변수!

그래서 n, 과 c에 값이 들어왔다고해서 String name, String color가 바뀌는것은 아니다
왜냐하면 이 둘은 heap이 들고 있는 변수기 때문! 

메모리 공간이 다르다 . 개발자가 직접 생성한 생성자는 Stack공간에 있고

직접 생성한 생성자(메서드)의 메모리 공간은 Stack이다
이 둘은 heap공간에 있다.

저둘은 heap공간에 있다. 

name = n;
color = c;

이 두개로 Stack공간에 있는 값들을 Heap공간으로 옴겨주는 것이다. 

이러고 다시 실행하면

상태 값에도 다 나온다!  

1) 그래서 클래스를 만들때 규칙이 있다. 상태를 초기화 하지 않는다.

public class Cat {
	String name;
	String color;

 

 

2) 초기화는 생성자를 통해서 한다! 생성자를 통해서 값을 받으면 그건 지역변수이기 떄문에 

Stack이 가진 변수다 생명력이 짧기 때문에 Heap공간 상태로 옮긴다! 

//개발자가 직접 생성자 구현함 = 디폴트 생성자가 생기지 않음.
	public Cat(String n, String c) { // 생성자 (메서드) 
		System.out.println("고양이 탄생함");
		System.out.println("n : " + n);
		System.out.println("c : " + c);
		
		// String n, String c는 지역변수 = Cat() 이라는 생성자(메서드) 가 가진 변수
		name = n;
		color = c;
	}
}

3) 디폴트 생성자는 언제만 생긴다고? 내가 생성자를 직접 구현하지 않았을떄만 생긴다! 

내가 직접 구현하지 않으면 디폴트 생성자는 있는것이다. 

// Cat() 생성자를 디폴트(기본) 생성자라고 한다. ( 디폴트 생성자) 
	// 개발자가 적지 않아도 있는 것!!( 생략 가능한 코드) 
	// 내가 직접 생성자를 구현하게 되면 디폴트 생성자가 생략 될수 없다.
	// 개발자가 생략 가능한 코드 
	public Cat() {
		
	}
	
	//개발자가 직접 생성자 구현함 = 디폴트 생성자가 생기지 않음.
	public Cat(String n, String c) { // 생성자 (메서드) 
		System.out.println("고양이 탄생함");
		System.out.println("n : " + n);
		System.out.println("c : " + c);
		
		// String n, String c는 지역변수 = Cat() 이라는 생성자(메서드) 가 가진 변수
		name = n;
		color = c;
	}
}

 

내가 직접 구현하지 않으면? 

package ch04;

//값을 초기화 하지 않는 이유는 new 할때마다 다른 상태를 가진 고양이를 만들기 위해서이다!!
public class Cat {
	String name;
	String color;
	
}

디폴트 생성자는 있는것이다! 

내가 구현하는 순간? 

package ch04;

//값을 초기화 하지 않는 이유는 new 할때마다 다른 상태를 가진 고양이를 만들기 위해서이다!!
public class Cat {
	String name;
	String color;
	
	// Cat() 생성자를 디폴트(기본) 생성자라고 한다. ( 디폴트 생성자) 
	// 개발자가 적지 않아도 있는 것!!( 생략 가능한 코드) 
	// 내가 직접 생성자를 구현하게 되면 디폴트 생성자가 생략 될수 없다.
	// 개발자가 생략 가능한 코드 
	public Cat() {
		
	}
	
	//개발자가 직접 생성자 구현함 = 디폴트 생성자가 생기지 않음.
	public Cat(String n, String c) { // 생성자 (메서드) 
		System.out.println("고양이 탄생함");
		System.out.println("n : " + n);
		System.out.println("c : " + c);
		
		// String n, String c는 지역변수 = Cat() 이라는 생성자(메서드) 가 가진 변수
		name = n;
		color = c;
	}
}

디폴트 생성자가 없는것이다. 그래서 직접 필요하면 직접 만들어줘야한다! 

지금은 필요 없지만 필요하다면 직접 만들어줘야한다! 

 

이 어려운개념이 객체지향 문법 말고 객체지향 이해에 들어가면 다 이해 할 수 있다! 

지금다 이해 안가더라도 흘려들어도 나중에 다 이해 할수 있다.!

 

가장 중요한것은 문법이기 때문에! 디폴트 생성자는 안적어도되는것 내가 만들면 컴파일러가 안만들어준다

Dog 같은 경우는 디폴트 생성자가 없다.

디폴트 생성자가 안보인다?

( 눈에 안보인다) 안보여도

.class 컴파일 할떄 자동으로 자바가 만들어준다!

.class로 컴파일 할때 없어도 자동으로 만들어준다!

이런걸 디폴트 생성자라고한다!