앞서 객체의 개념에 대해 공부하며 생성자를 언급한 적이 있다.
참고) 객체의 개념
이번 게시물에서는 '생성자'가 무엇이고, 어떤 역할을 하는지 조금 더 자세히 알아보자.
생성자의 개념을 이해하기 위해 먼저 클래스의 전체 구조를 생략 없이 전부 명시해보았다.
package kr.s15.object.constructor;
class Car{
//멤버 변수
String color;
String gearType;
int door;
//기본 생성자
public Car() {}
}
public class CarMain01 {
public static void main(String[] args) {
//객체 선언 및 생성
Car c1 = new Car();
System.out.println(c1.color + ", " + c1.gearType + ", " + c1.door);
//멤버 변수의 데이터 변경
c1.color = "white";
c1.gearType = "auto";
c1.door = 4;
System.out.println(c1.color + ", " + c1.gearType + ", " + c1.door);
}
}
기존 예제와 달리, 기본 생성자라는 항목이 눈에 띈다. 앞선 예제에서 객체를 생성할 때는 생략하였기 때문이다.
여기서 알 수 있듯 public Car() {}와 같은 기본 생성자는 생략 가능하며, 이는 컴파일 시에 컴파일러가 생략된 기본 생성자를 만들어 주기 때문이다.
그리고 생성자는 객체 생성 시 단 한 번 실행되고 객체 생성 이후에는 호출이 불가능하다.
호출 시에는 1) 멤버변수를 초기화하는 역할을 수행한다. 따라서 위 예제에서 명시한 String color;와 같이 멤버변수들에 값을 대입하지 않고
System.out.println(c1.color + ", " + c1.gearType + ", " + c1.door); 출력하였을 경우,
출력)
null, null, 0
기본값이 출력되는 것을 확인할 수 있다.
따라서 우리는 초기화를 담당하는 생성자를 '오버로딩'하여 기본값이 다양한 객체들을 생성할 수 있다.
package kr.s15.object.constructor;
class Car2{
String color;
String gearType;
int door;
//생성자 오버로딩
public Car2() {}
public Car2(String c, String g, int d) {
color = c;
gearType = g;
door = d;
}
}
public class CarMain02 {
public static void main(String[] args) {
Car2 c1 = new Car2();
c1.color = "white";
c1.gearType = "auto";
c1.door = 2;
System.out.println(c1.color + "," + c1.gearType + "," + c1.door);
System.out.println("=========================");
//인자가 있는 생성자로 출력하기
Car2 c2 = new Car2("blue", "manual", 5);
System.out.println(c2.color + "," + c2.gearType + "," + c2.door);
}
}
메서드처럼 생성자 오버로딩이 가능해 한 클래스는 기본 생성자 외에 같은 이름을 가진 다른 생성자를 가질 수 있다.
참고) 메서드 오버로딩
단, 기본 생성자 없이 생성자 오버로딩을 한 다른 생성자만 존재할 경우, 컴파일러가 기본 생성자를 생성하지 않기 때문에 기본 생성자로 객체를 생성하려고 할 경우 오류가 발생한다.
ex)
public Car2(String c, String g, int d) {
color = c;
gearType = g;
door = d;
}
위에서 배운 생성자 오버로딩 개념을 적용하여 성적 프로그램을 만들어보았다.
> 생성자를 활용해 성적 프로그램 만들기
또한, 9월 8일 생성자 오버로딩과 은닉화/캡슐화, this 개념을 적용하여 실습을 진행하였다.
참고) 은닉화/캡슐화
참고) this/tihs()
* [실습]
* 1. 멤버 변수: 이름(name), 나이(age), 비행 여부(fly)
* 2. 생성자 지정: 인자 없는 생성자, 인자가 있는 생성(name, age, fly)
* 3. set/get 지정 : 멤버 변수를 private으로 지정하고 public한 set/get 메서드 정의
* [실습]
* 1. 객체 생성 : 인자가 있는 생성자로 객체 생성
* 2. 생성된 객체의 멤버 변수에 저장된 정보 출력
* 이름 : 기러기
* 나이 : 3살
* 비행 여부 : 가능
* 3. 객체 생성 : 인자가 없는 생성자로 객체 생성
* 4. 이름, 나이, 비행 여부를 저장
* 5. 생성된 객체의 멤버 변수에 저장된 정보 출력
* 이름 : 기린
* 나이 : 10살
* 비행 여부 : 불가능
package kr.s17.object.trainning;
public class Animal {
private String name;
private int age;
private boolean fly;
public Animal() {}
public Animal(String name, int age, boolean fly) {
this.name = name;
this.age = age;
this.fly = fly;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setFly(boolean fly) {
this.fly = fly;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean isFly() {
return fly;
}
}
문제에 따라 멤버 변수를 private으로 지정(은닉화)한다.
Animal 클래스의 인자가 없는 생성자 즉, 기본 생성자를 만든다.
ex. public Animal(){}
생성자 오버로딩을 통해 인자가 있는 생성자를 만든다. 이때, 인자로 전달받은 name, age, fly를 객체의 은닉화된 멤버 변수에 대입해준다.
ex. this.name = name;
아래 과정을 통해 캡슐화(set(), get() 메서드 정의)을 진행한다.
① 마우스 우클릭
② source
③ Generate Getters and Setters
④ select All > Generate 클릭

이때 눈여겨볼 것은 boolean 타입의 은닉화된 변수에서 데이터를 뽑아내는 메서드는 getFly()가 아닌 isFly()라는 점이다.
package kr.s17.object.trainning;
public class AnimalMain {
public static void main(String[] args) {
Animal first = new Animal("독수리", 5, true);
System.out.println("이름 : " + first.getName());
System.out.println("나이 : " + first.getAge() + "살");
System.out.println("비행 여부 : " + printFly(first.isFly()));
System.out.println("===============");
Animal second = new Animal();
second.setName("말티즈");
second.setAge(2);
second.setFly(false);
System.out.println("이름 : " + second.getName());
System.out.println("나이 : " + second.getAge() + "살");
System.out.println("비행 여부 : " + printFly(second.isFly()));
}
public static String printFly(boolean fly) {
return fly ? "가능" : "불가능";
}
}
인자가 있는 생성자 public Animal(String name, int age, boolean fly) {의 경우, 인자로 각 타입에 맞는 데이터를 객체 생성 시에 바로 넘겨주면, 멤버 변수에 전달 받은 데이터를 대입 this.age = age; 해준다. 따라서 set() 메서드를 사용할 필요가 없다.
출력 시에는 은닉화되어 있는 멤버 변수에 get() 메서드로 접근해 값을 읽어온다.
ex. System.out.println("이름 : " + first.getName());
이때 first.isFly()와 같은 boolean 타입은 true 혹은 false로 데이터가 출력되는데, 실습 문제에 따르면 '가능'과 '불가능'이 표기되어야 한다.
따라서 boolean 타입의 데이터를 한 번 가공하기 위해 조건(삼항) 연산자를 사용한다.
참고) 5. 조건(삼항) 연산자
메인 영역 바깥에서 boolean 타입의 데이터를 인자로 받고, String 타입의 데이터를 반환하는 메서드를 생성한다.
ex. public static String printFly(boolean fly) {
return 값을 명시할 때, 조건(삼항) 연산자를 넣어 전달 받은 boolean 타입의 데이터를 조건 체크 해주고, 참이면 "가능" 거짓이면 "불가능"을 반환하게 한다.
ex. return fly ? "가능" : "불가능";
[boolean 타입의 데이터 출력 과정]
① isFly() 메서드를 통해 Animal 객체의 boolean 타입 데이터 fly를 반환한다.
② 그 값(fly)은 printFly() 메서드의 인자로 전달된다.
③ 그 값이 true면, "가능"을 반환하고
④ false라면, "불가능"을 반환한다.
따라서 비행 여부를 명시할 경우에는 isFly() 메서드를 PrintFly() 메서드로 감싼다.
ex. System.out.println("비행 여부 : " + printFly(first.isFly()));
인자가 없는 생성자 public Animal() {}의 경우, 객체만 먼저 생성한다.
그리고 set() 메서드를 통해 각 타입에 맞는 메서드를 인자로 넘겨 멤버 변수에 저장해준다.
ex. second.setName("말티즈");
출력 시에는 get() 메서드를 호출, boolean 타입의 메서드는 PrintFly()로 감싼 isFly() 메서드를 호출한다.