생성자

#JAVA #생성자 #클래스와 객체
Dec 31, 2023
생성자

1. 생성자 (Constructor) 란?

💡
객체가 생성될 때 무조건 실행되는 메서드. 객체 초기화(=최초값 세팅)를 위해 사용하는 것. 클래스의 인스턴스(객체)가 생성될 때 한 번만 호출된다. 생성자 이름은 클래스 이름과 같다. 반환값을 가지지 않는다. 보통은 생략되어서 보이지 않고(기본생성자), 별도로 선언하지 않더라도 자동으로 생성된다.
 
* 생성자도 메소드! > 오버로딩을 할 수 있다, 매개변수를 가질 수 있다 * 생성자를 통해 객체가 생성 * 생성자가 때려졌다 = 이미 new가 되었다. (heap에 만들어졌다.)
notion image
맛보기
<CircleTest Class>
notion image
Circle()은 생성자다. 생성자를 작성하지 않으면 자동 생성됨. (눈에는 안보임)
notion image
생성자를 작성한 모습
 
<CircleTest Class>
notion image
 
<Circle Class>
notion image
new가 실행되기 전에 static이 붙지 않은 애들이 메모리에 다 뜸. 여기선 radius랑 getArea가 뜸. getArea는 메소드니 제외하고, Circle obj = new Circle();이란 말은 radius는 값이 없는 상태.
Circle obj = new Circle(50); 이렇게 생성자에 값을 넣으면 최초로 만들어질 때, (new 띄울 때, 기본값이 50) radius 값이 50이 된다는 말. = CircleTest에서 최초값을 세팅했음!
 
<결과값>
notion image
 
💡
객체 초기화 > 생성자 시간이 지나면서 변화하는 것 > 메서드

2. 생성자의 매개변수

notion image
분홍색 표시 코드를 보면, Pizza는 매개변수가 없다. (디폴트 생성자) 즉, 초기값으로 세팅된건 없고, 8번, 9번 값으로 초기화를 받는다. //결과 - type 슈퍼슈프림, size 12 노란색 표시 코드를 보면, 매개변수가 2가지 (int s, String t)가 들어가있다. (생성자) 그래서 new Pizza(24, "포테이토") 라고 초기값을 넣어준 것!! //결과 - type 포테이토, size 24 초기에 세팅된 값이 그대로 출력되는 걸 알 수 있다!!
 

2-1. 생성자에 매개변수를 사용하는 이유?

  • 객체를 생성하고 초기화하는 과정에서 필요한 데이터를 전달하기 위함
  • 객체를 생성할 때, 객체의 초기 상태를 설정해야 하는 경우가 많다. 예를 들어, People 클래스에서는 name, power, hp라는 속성을 가지고 있다. People 객체를 생성할 때, (=new 할 때) 해당 객체의 name과 power의 초기값을 (객체를 생성할 때마다 내가 원하는 초기값으로) 입력 받고 싶다.
  • 이때 생성자를 사용하면 객체 생성과 동시에 초기 데이터를 전달할 수 있다. 생성자에 매개변수를 정의하고, 객체를 생성할 때 해당 매개변수에 전달된 값을 이용하여 객체의 속성을 초기화할 수 있다.
 

IntelliJ 생성자 자동 생성
(1) Alt + Insert → Constructor
(1) Alt + Insert → Constructor
 
(2) 만들 생성자 선택 후, OK
(2) 만들 생성자 선택 후, OK
 
(3) 결과
(3) 결과
생성자 오버로딩 예제
생성자 오버로딩 예제 1.
package ex04; class Pizza{ int size; String type; // 생성자 --> 매개 변수가 없는 타입 public Pizza() { size = 12; type = "슈퍼슈프림"; } // 생성자 --> 매개 변수가 있는 타입 public Pizza(int s, String t) { size = s; type = t; } } public class PizzaTest { public static void main(String[] args) { Pizza p1 = new Pizza(); System.out.println("("+p1.type+", "+p1.size+",)"); Pizza p2 = new Pizza(24, "포테이토"); System.out.println("("+p2.type+", "+p2.size+",)"); } }
 
// 실행 값 (슈퍼슈프림, 12,) (포테이토, 24,)
 
생성자도 메서드이기 때문에 오버로딩 할 수 있다.
객체의 참조 변수 명을 다르게 만들어 heap에 띄우고
Pizza p1 = new Pizza(); —> 객체가 생성 될때 초기화
Pizza p2 = new Pizza(24, "포테이토"); —> 객체가 생성 될때 초기화
 
  • 첫번째, 매개 변수가 없는 생성자를 호출
    • 생성자는 객체를 new 로 heap에 띄울때 자동으로 한번 호출된다.
 
  • 두번째, 매개 변수가 있는 생성자를 호출
    • (int s, String t)라는 매개 변수를 정의하고 이것이 실행될때 size와 type이 초기화 된다.
      heap 띄우고 호출할때 타입에 맞춰 값을 넣어 전달한다.
       
첫번째 생성자를 호출하면 size 는 무조건 12가 되고 type 은 슈퍼슈프림이 나오고
두번째 생성자를 호출하면 내가 원하는 size 의 type 이 나온다.
생성자는 생성자 오버로딩을 통해 초기화 할 수 있다는 걸 알 수 있다.
 

 
Private가 있는 생성자 오버로딩 예제 2.
Telvision 클래스에 생성자를 추가하여 업그레이드 해보자. —> 상태값에 private 붙이란 이야기
생성자는 객체가 생성 될때 channel, volume, onOff 변수를 초기화 한다.
package ex04; class Telvision{ // 상태값 private int channel; private int volume; private boolean onOff; // 생성자 (값에 private 붙여 놔서 강제성이 부여됨 초기화는 당연히 생성자로 한다.) public Telvision(int c, int v, boolean o){ channel = c; volume = v; onOff = o; // thtis 안붙인 이유 --> 변수의 이름이 달라서 충돌날 일이 없다. } // 확인용 메서드 // void print(){ // 반환 값이 없음 // System.out.println("채널은 " + channel + "이고 볼륨은 " + volume + "입니다."); // } public String toString(){ return "채널은 " + channel + "이고 볼륨은 " + volume + "입니다."; } } public class TelvisionEx02 { public static void main(String[] args) { Telvision myTv = new Telvision(7,10,true); // myTv.print(); System.out.println(myTv.toString()); Telvision yourTv = new Telvision(9, 12, true); // yourTv.print(); System.out.println(yourTv.toString()); } }
 
Telvision 클래스의 상태값에 전부 private 를 붙여 접근하지 못하게 하고
생성자로 부터 간접적으로 객체를 초기화 한다.
생성자는 매개 변수를 (int c, int v, boolean o) 정의하여
channel, volume, onOff 에 변수를 초기화 한다.
객체의 참조 변수 명을 다르게 만들어 heap에 띄우고 타입에 맞춰 값을 넣어 전달
Telvision myTv = new Telvision(7,10,true);
Telvision yourTv = new Telvision(9, 12, true);
myTv 와 yourTv 의 채널과 볼륨을 알아보자.
교재의 예제에서는 print() 메서드를 써서 확인 했지만
toString() 사용해서 return 값을 반환해보겠다.
 
// 실행 값 채널은 7이고 볼륨은 10입니다. 채널은 9이고 볼륨은 12입니다.

2. 기본 생성자 (Default Constructor)

기본 생성자는 매개 변수를 받지 않고, 객체를 초기화하는 생성자이다. → 매개변수를 가지지 않고 클래스의 객체를 생성하는 생성자. (매개 변수가 없는 생성자)
기본 생성자는 매개변수 없이 객체를 만들 때 호출되며, 클래스 내에 명시적으로 정의하지 않을 경우에도 컴파일러가 자동으로 기본 생성자를 생성해준다.
간단히 말해 만약 개발자가 생성자를 하나도 정의 하지 않았다면, 자바 컴파일러는 기본 생성자를 자동으로 만든다.
이때, 모든 멤버 변수들을 기본값으로 초기화한다. ex) toString 안의 내용 참조 (lamp)
 
Default 생성자 예제
package ex04; class Box { int width; int length; int height; // 기본생성자 public Box(){ // 매개 변수를 받지 않음 // 아무런 작업을 수행하지 않음 } } public class BoxTest { public static void main(String[] args) { Box b = new Box(); System.out.println("상자의 크기: (" + b.width + ", " + b.length + ", " + b.height + ")"); } } // 실행 값 상자의 크기: (0, 0, 0)
기본 생성자는 매개변수를 가지지 않고 클래스의 객체를 생성하는 역할을 하며, 주로 멤버 변수를 기본값으로 초기화하는 용도로 사용
 

3. ★ 기본 생성자가 추가 되지 않는 경우 !! ★

개발자가 생성자를 하나 라도 선언하면, 컴파일러는 기본 생성자를 추가하지 않는다.
 
Default 생성자 추가 되지 않는 경우 예제
package ex04; class Box { int width, length, height; // 개발자가 생성자를 만들었기 때문에 // 더이상 디폴트 생성자가 아니다! public Box(int w, int h, int d){ width = w; length = h; height = d; } } public class BoxTest { public static void main(String[] args) { Box b = new Box(); // 오류 발생 System.out.println("상자의 크기: (" + b.width + ", " + b.length + ", " + b.height + ")"); } }
 
Box b = new Box(); // 오류 발생 하는데 —> Box() 라고하는 기본 생성자가 정의 되지 않았다.
개발자가 매개변수가 있는 형태의 생성자를 만들었기 때문에
컴파일러는 기본 생성자를 추가 하지 않는다.
왜냐하면 개발자가 Box 객체를 생성할때 반드시 박스의 크기를 지정해야 한다고
의도 했을 수 있기 때문에 컴파일러가 개발자의 의도를 거스를 수 없기 때문이다.
그런데 컴파일러가 기본 생성자를 추가 해버리면 개발자의 의도가 훼손이 된다.
 
// 실행값 // 오류 발생 C:\workspace\untitled\src\ex04\BoxTest.java:15:17 java: constructor Box in class ex04.Box cannot be applied to given types; required: int,int,int found: no arguments reason: actual and formal argument lists differ in length
 
기본 생성자를 수기로 생성해 준 모습
notion image
오류가 뜨지 않는 것 확인!
 
💡
개발자가 생성자를 하나 라도 선언하면, 컴파일러는 기본 생성자를 추가하지 않는 이유를
꼭 기억하자!!
 
개발자가 클래스에 생성자(=매개 변수가 있는 것)를 하나라도 선언한다면 컴파일러는 기본 생성자(=매개 변수 X)를 자동으로 추가하지 않는다.
원래는 자동으로 생성 해줬는데... 수기 생성 해야한다.
개발자가 생성자를 하나라도 정의하면 컴파일러는 해당 생성자를 기본 생성자로 간주하고, 추가적으로 기본 생성자를 생성하지 않는다.
 

4. 생성자와 메서드 구분

생성자는 클래스의 이름과 동일한 이름을 가지고 있다 (대문자로 시작), 리턴값 없다. 객체를 초기화하고 생성하는 역할. (태어나면서부터 가지는 값) ex) public Person() { 메소드는 객체의 동작이나 기능을 정의하고 구현하는 역할을 하며 객체를 통해 호출된다. 리턴값 있다. 소문자. 라마표기법. (살아가면서 느는 것) ex) public int minus() { * 매개변수는 둘 다 가질 수 있다!
강의 예제
package ex04; //설계도 class People { String name; //애의 스코프는 heap int power; int hp; //객체 초기화할때 사용 public People(String name, int power) { //애의 name은 스코프가 stack //값을 전달받아서 객체의 상태값으로 옮김. this.name = name; //this는 스코프가 heap에 있는 애를 이야기함 this.power = power; this.hp = 100; //생성할 때마다 hp는 100으로 고정이니 애는 상수로 받는다. } //초기값이 아니라, 살아가면서 느는거라(?) 메소드 (행위) public void upgradePower() { this.power++; } @Override public String toString() { return "People{" + "name='" + name + '\'' + ", power=" + power + ", hp=" + hp + '}'; } } public class PersonEx01 { public static void main(String[] args) { People p1 = new People("티모", 10); System.out.println(p1); p1.upgradePower(); System.out.println(p1); } }
notion image
notion image

💡
클래스의 객체를 생성자로 전달하는 경우, 별도의 생성자를 구현할 필요는 없다. 생성자는 객체를 초기화하기 위해 사용되는 특별한 메서드로서, 클래스의 인스턴스를 생성할 때 호출된다. 클래스의 생성자는 일반적으로 인스턴스 변수를 초기화하거나 필요한 설정을 수행하는 역할을 한다. 그러나 이미 생성된 객체를 생성자로 전달받는 경우, 해당 객체는 이미 생성 및 초기화된 상태이므로 별도의 생성자를 구현할 필요가 없다.
 
Share article

Coding_study