생성자
생성자는 인스턴스가 생성될 떄 호출되는 '인스턴스 초기화 메서드'이다. 주로 인스턴스 변수의 초기화 작업에 사용되며, 인스턴스 생성 시에 실행되어야 할 작업을 위해서도 사용된다.
생성자 역시 메서드처럼 클래스 내에 선언되며, 구조도 메서드와 유사하지만 리턴값이 없다는 차이점이 있다. 그렇다고 생성자 앞에 리턴값 이 없음을 뜻하는 void를 사용하지는 않고, 아무 것도 적지 않는다.
생성자는 오버로딩이 가능하기 때문에 하나의 클래스에 여러 개의 생성자가 존재할 수 있다.
생성자는 다음과 같은 조건을 가진다.
1. 생성자의 이름은 클래스의 이름과 같아야 한다.
2. 생성자는 리턴 값이 없다.
기본 생성자
모든 클래스에는 반드시 하나 이상의 생성자가 정의되어 있어야 한다. 하지만 지금까지 클래스에 생성자를 정의하지 않고도 인스턴스를 생성할 수 있었던 이유는 컴파일러가 제공하는 '기본 생성자' 덕분이다.
컴파일러가 자동적으로 추가해주는 기본 생성자는 매개변수도 없고 아무런 내용도 없는 아주 간단한 것이다. 특별히 인스턴스 초기화 작업이 요구되어지지 않는다면 생성자를 정의하지 않고 컴파일러가 제공하는 기본 생성자를 사용하는 것도 좋다
매개변수가 있는 생성자
생성자도 메서드처럼 매개변수를 선언하여 소출 시 값을 넘겨 받아서 인스턴스의 초기화 작업에 사용할 수 있다.
생성자를 사용하지 않은 예
class car {
String color; //색상
String gearType; //변속기 종류 = auto(자동), manual(수동)
int door; //문의 개수
}
public class Constructor1 {
public static void main(String[] args) {
car c = new car();
c.color = "white";
c.gearType = "auto";
c.door = 4;
}
}
이 예제는 car 클래스로 인스턴스 c를 생성하고 인스턴스 변수들을 초기화하는 것을 나타낸 것이다. 인스턴스 변수의 초기화를 위해서는, 인스턴스를 생성한 다음에 인스턴스 변수들을 초기화하는 과정이 추가로 필요하다.
생성자를 사용한 예
class car {
String color; //색상
String gearType; //변속기 종류 = auto(자동), manual(수동)
int door; //문의 개수
car(String c, String g, int d) { //생성자
color = c;
gearType = g;
door = d;
}
}
public class Constructor1 {
public static void main(String[] args) {
car c = new car("white", "auto", 4); //생성자 호출
}
}
위의 예제는 car 클래스에 car(String c, String g, int d) 생성자를 선언하고, 이를 통해 car 클래스로 생성한 인스턴스 c를 초기화하는 코드다.
생성자를 사용하면 인스턴스를 생성함과 동시에 인스턴스 변수들을 초기화할 수 있다. 코드를 보다 간결하고 직관적으로 만들 수 있는 것이다.
생성자에서 다른 생성자 호출하기
같은 클래스의 맴버들 간에 서로 호출할 수 있는 것처럼 생성자 간에도 서로 호출이 가능하다. 단, 다음 두 조건을 만족시켜야 한다.
1. 생성자의 이름으로 클래스 이름 대신 this를 사용한다.
2. 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다.
아래 예제는 생성자를 작성할 때 지켜야 하는 두 조건을 모두 만족시키지 못했기 때문에 오류가 발생한다.
Car(String color) {
door = 5;
Car(color, "auto", 4); //에러1. 생성자의 첫 번째 줄에서 호출하지 않았음
//에러2. this(color, "auto", 4);로 호출하지 않았음
}
이제 올바르게 생성자를 호출하는 코드를 보자.
class car {
String color; //색상
String gearType; //변속기 종류 = auto(자동), manual(수동)
int door; //문의 개수
car() { //생성자 1번
this("white", "auto", 4); //생성자 3번 호출
}
car(String color) { //생성자 2번
this(color, "manual", 4); //생성자 3번 호출
}
car(String color, String gearType, int door) { //생성자 3번
this.color = color;
this.gearType = gearType;
this.door = door;
}
}
public class Constructor2 {
public static void main(String[] args) {
car c1 = new car();
car c2 = new car("blue");
System.out.println("c1의 정보 : " + c1.color + ", " + c1.gearType + ", " + c1.door);
System.out.println("c2의 정보 : " + c2.color + ", " + c2.gearType + ", " + c2.door);
}
}
실행 결과 c1의 정보 : white, auto, 4 c2의 정보 : blue, manual, 4 |
위 예시는 생성자 car()에서 또 다른 생성자 car(String color, String gearType, int door)를 호출하였다. 이처럼 생성자 같의 호출에는 생성자의 이름 대신 this를 사용해야 하고, 첫째 줄에서 호출하였다는 점을 알아두길 바란다.
car(String color, String gearType, int door) { //생성자 3번
this.color = color;
this.gearType = gearType;
this.door = door;
}
추가로 알아둘 점은 car(String color, String gearType, int door) 생성자 내에서 color라는 변수에 대해 어떻게 표현하였는지 살펴봐야 한다. color라는 변수가 car(String color, String gearType, int door) 생성자에서 선언된 로컬 변수인지, car 클래스 안에서 선언된 인스턴스 변수인지 구별하기 위해 인스턴스 변수 앞에는 'this'를 붙여 표현하였다.
생성자를 이용한 인스턴스의 복사
현재 사용하고 있는 인스턴스와 같은 상태를 갖는 인스턴스를 하나 더 만들고자 할 때 생성자를 사용할 수 있다. 두 인스턴스가 같은 상태를 갖는다는 것은 두 인스턴스의 모든 인스턴스 변수가 동일한 값을 갖고 있다는 것을 뜻한다.
인스턴스의 복사를 위해서는 Object 클래스의clone 메서드를 사용하면 간단하게 해결할 수 있지만 생성자를 통한 복사도 알아보도록 하자.
class car {
String color; //색상
String gearType; //변속기 종류 = auto(자동), manual(수동)
int door; //문의 개수
car() {
this("red", "manual", 2);
}
car(car c) { //인스턴스의 복사를 위한 생성자
color = c.color;
gearType = c.gearType;
door = c.door;
}
car(String color, String gearType, int door) {
this.color = color;
this.gearType = gearType;
this.door = door;
}
}
public class copyInstance {
public static void main(String[] args) {
car c1 = new car();
car c2 = new car(c1);
System.out.println("c1의 정보 : " + c1.color + ", " + c1.gearType + ", " + c1.door);
System.out.println("c2의 정보 : " + c2.color + ", " + c2.gearType + ", " + c2.door);
}
}
실행 결과 c1의 정보 : red, manual, 2 c2의 정보 : red, manual, 2 |
인스턴스 c2는 c1을 복사하여 생성된 것이므로 서로 같은 상태(인스턴스 변수가 동일)를 갖지만, 서로 독립적으로 메모리 공간에 존재하는 별도의 인스턴스이므로 c1의 값들이 변경되어도 c2는 영향을 받지 않는다.
총평
자바의 정석 책의 chapter 06 - 객체지향 프로그래밍1의 정리가 끝났다.
이 책을 보면서 내가 객체지향 프로그래밍에 대해 정말 하나도 모르는 수준이었다는 것을 느끼게 되었다.
다음 챕터인 객체지향 프로그래밍2에서는 상속, 다형성 같은 내용을 다뤄보겠다.
'✏️Java 공부 > Java의 정석' 카테고리의 다른 글
[Java 공부/Java의 정석] Chapter.07 : 객체지향 프로그래밍 2 - 2 (오버라이딩) (0) | 2022.07.06 |
---|---|
[Java 공부/Java의 정석] Chapter.07 : 객체지향 프로그래밍 2 - 1 (상속) (0) | 2022.07.04 |
[Java 공부/Java의 정석] Chapter.06 : 객체지향 프로그래밍 1 - 4 (오버로딩) (0) | 2022.07.01 |
[Java 공부/Java의 정석] Chapter.06 : 객체지향 프로그래밍 1 - 3 (기본형 매개변수와 참조형 매개변수) (0) | 2022.07.01 |
[Java 공부/Java의 정석] Chapter.06 : 객체지향 프로그래밍 1 - 2 (변수와 메서드) (0) | 2022.07.01 |
댓글