[JAVA] JAVA 프로그래밍 기초 교육 : 생성자 & 오버로드
교재 : JAVA 프로그래밍 기초 - 13. 생성자 / 14. 오버로드
+ 자바의 정석[기초편]
# 생성자(constructor)
생성자란? 인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메소드'
[생성자 특징]
- 생성자의 이름은 클래스의 이름과 같아야 한다.
- 생성자는 리턴 값이 없다. (모든 생성자가 리턴 값이 없으므로 void를 생략할 수 있게 하였다.)
- 인스턴스 변수(필드변수)들의 초기화에 사용되는 특별한 메소드이다.
- 모든 클래스에 존재하여 오브젝트 작성 시에 반드시 사용된다.
- 생성자 앞에 private 한정자를 걸고 다른 클래스에서 호출 시 외부 엑세스가 불가능하여 컴파일 오류가 난다.
[생성자 정의]
클래스이름(타입 변수명, 타입 변수명, …) {
// 인스턴스 생성 시 수행될 코드,
// 주로 인스턴스 변수의 초기화 코드를 적는다.
}
* [생성자 종류] *
- 디폴트 constructor
- 인수 없는 constructor
- 인수 있는 constructor
* 기본 생성자(default constructor)
- 인수(매개변수)도 없고 아무런 내용도 없을 때 컴파일러가 자동적으로 '기본 생성자'를 추가*하여 컴파일한다.
- 클래스에 정의된 생성자가 하나도 없을 때만 컴파일러에 의해 기본 생성자가 추가된다.
(반대로 생성자가 하나라도 있을 시에는 자동으로 추가되지 않음)
class 클래스명 () {}
public class 클래스명 {
필드 변수명
...
메소드
...
}
(접근제어자가 public인 경우)
* 생성자 정의가 없을 시에 컴파일러가 자동으로 추가하는 생성자 형식
(접근 한정자) 클래스명() {
super();
}
super() : 조상의 생성자를 호출(조상 클래스가 있을 시에 사용)
생성자 정의가 없는 클래스의 객체화(인스턴스화)
클래스명 변수명 = new 클래스명();
// 예시
Computer1 com = new Computer1();
* 인수(매개변수)가 없는 생성자
- 클래스 블록 내에 정의한다.
- 이름은 클래스명과 같고 리턴 값(반환값)의 형태는 지정하지 않는다. (=void도 기술하지 않음)
public class 클래스명 {
필드 변수명
...
public [ ] 클래스명() {
// 초기 설정값 등
}
메소드
...
}
※주의 : 생성자에 리턴값 형태를 설정하면 클래스명과 같은 이름을 가진 단순한 메소드가 되어버리니 주의할 것.
* 인수(매개변수)가 있는 생성자
- 형식은 인수가 없는 생성자와 같은데 인수를 설정하는 것이 포인트.
- 인수가 있는 생성자를 사용 시 인스턴스를 생성하는 동시에 원하는 값으로 초기화가 가능하다.
public class 클래스명 {
필드변수명
...
public [ ] 클래스명(인수) {
// 초기화 내용
}
메소드
...
}
[예제] 인수가 없는 생성자 ↔ 인수가 있는 생성자 비교 ①
package javaex.chap6;
class Car {
String color;
String gearType;
int door;
Car(){}
Car(String c, String g, int d){
color = c;
gearType = g;
door = d;
}
}
public class ex34 {
public static void main(String[] args) {
Car c1 = new Car();
c1.color = "white";
c1.gearType = "auto";
c1.door = 4;
Car c2 = new Car ("White", "auto", 4);
System.out.println("c1의 color = " + c1.color + ", gearType = " + c1.gearType + ", door = " + c1.door);
System.out.println("c2의 color = " + c2.color + ", gearType = " + c2.gearType + ", door = " + c2.door);
}
}
자바의 정석[기초편] 199p
인수가 있는 생성자를 사용 시에 코드가 더 간결하고 직관적이다.
▽ 실행 결과 ▽
[예제] 인수가 없는 생성자 ↔ 인수가 있는 생성자 비교 ②
package jokun.chap13;
class Computer2{
String os;
int memory;
//인수가 없는 생성자
Computer2 () {}
//인수가 있는 생성자
public Computer2 (String os, int memory){
//필드변수에 초기값 설정
this.os = os;
this.memory = memory;
System.out.println("OS는 " + this.os + "이고, 메모리는 " + this.memory + "GB의 PC가 만들어졌습니다.");
}
public void show(){
System.out.println("PC의 OS는 " + os + "입니다.");
System.out.println("메모리는 " + memory + "GB입니다.");
}
}
public class Constructor2 {
public static void main(String[] args) {
Computer2 c2 = new Computer2();
c2.os = "windows 10";
c2.memory = 16;
System.out.println("=== 인수가 있는 생성자 실행 전 ===");
Computer2 com = new Computer2("Windows 11", 32);
System.out.println("=== 인수가 있는 생성자 실행 후 ===");
com.show();
System.out.println("=== 인수가 없는 생성자===");
System.out.println("PC의 OS는 " + c2.os + "입니다.");
System.out.println("메모리는 " + c2.memory + "GB입니다.");
}
}
▽ 실행 결과 ▽
[연습문제]
13-5. 연습문제
<질문1> 다음의 질문 ①~⑤에 대해 ○인가×로 대답하십시오.
① 클래스내에 정의할 수 있는 것에는 필드, 메소드 외에 constructor 가 있다. O
② 생성자의 이름은 자유롭게 붙일 수 있고, 반환값도 설정할 수 있다. X
③ 생성자에는 액세스 수식자를 붙일 수 없다. X
④ 디폴트 생성자를 호출하는 방법은 인수가 없는 생성자와 동일하다. O
⑤ 디폴트 constructor 은 constructor 을 정의하고 있어도 사용할 수 있다. X
<질문 2> 아래에 나타내는 Books 클래스의 생성자 정의의 에러를 3개 대답해 주세요.
① 소스 폴더: javabasic/src
② 패키지: chap13exercise
③ 이름: Books
package chap13exercise;
public class Books {
String title;
int price;
public void Book(String title, int price) {
this.title = price;
this.price = title;
System.out.println("이 책의 제목을 " + title + "이고 판매가격은" + price + 입니다.");
}
}
1. 리턴값 형태가 정의 되어있다.
2. Books - Book
3. title 변수에 대입하는 가인수가 잘못되어있음.
<질문 3> 이하의 필드를 가지는 클래스 Score1.java의, 초기화를 하는 인수 없는 constructor 을 정의해 주세요. String은 null, int(배열도 마찬가지)는 0, double는 0.0을 초기값으로 처리한다.
① 소스폴더: ㅓavabasic/src
② 패키지: chap13exercise
③ 이름: Score1
package chap13excercise;
public class Score1 {
String name; // 이름
int[] score = new int[5]; // 5꾜과 점수 저장용 배열
int total; // 총점
double ave; // 평균
}
▽ 답 ▽
package chap13excercise;
public class Score1 {
String name; // 이름
int[] score = new int[5]; // 5꾜과 점수 저장용 배열
int total; // 총점
double ave; // 평균
public Score1(){
this.name = null;
for(int i = 0; i < this.score.lenght; i++) {
this.score[i] = 0;
}
this.total = 0;
this.ave = 0.0;
}
}
<질문 4> 질문 3으로 나타낸 필드 선언된 부분의 클래스 Score1.java에, 인수 있는 생성자를 정의한 Score2.java를 작성해 주세요.
생성자 사양
- 인수는 다음의 4개를 정의한다.
제1 인수:String name 제2 인수:int[] score 제3 인수:int total 제4 인수: double ave - 인수의 값을 그대로 대응하는 필드에 설정한다. 그러나 배열 score는 하나씩 값을 취득하여 설정한다.
예제 this.score[0] = score[0];
① 소스폴더: javabasic/src
② 패키지: chap13exercise
③ 이름: Score2
package chap13excercise;
public class Score2 {
String name; // 이름
int[] score = new int[5]; // 5교과 점수 저장용 배열
int total; // 총점
double ave; // 평균점
public Score2(String name, int[] score, int total, double ave) {
// 인수 값으로 이름 설정
// 여기에 처리 설명
// 반복 문을 사용하여 인수 값으로 배열 설정
// 여기에 처리 설명
// 인수 값으로 총점 설정
// 여기에 처리 설명
// 인수 값으로 평균 점 설정
// 여기에 처리 설명
}
}
▽ 답 ▽
package jokun.chap13;
public class Score2 {
String name; // 이름
int[] score = new int[5]; // 5교과 점수 저장용 배열
int total; // 총점
double ave; // 평균점
public Score2(String name, int[] score, int total, double ave) {
// 인수 값으로 이름 설정
this.name = name;
// 반복 문을 사용하여 인수 값으로 배열 설정
for (int i =0; i < this.score.length; i++){
this.score[i] = score [i];
}
// 인수 값으로 총점 설정
this.total = total;
// 인수 값으로 평균 점 설정
this.ave = ave;
}
}
# 오버로드(overlload)
오버로드란? 한 클래스 내에 같은 이름의 메소드를 여러 개 정의하는 것.
'메소드 오버라이딩(method overloading) or '오버로딩(overloading)'이라 한다.
[오버로딩 조건]
- 메소드 이름이 같아야 한다.
- 인수(매개변수)의 개수 또는 타입이 달라야 한다.
- 반환 타입은 관계없다.
위의 조건들이 만족하지 못하는 메소드는 중복 정의로 간주되어 컴파일 오류가 난다.
[오버로딩하는 이유]
- 인터페이스에 일관성을 갖게 한다.
- 새로운 이름이나 이름 규칙을 생각해 내는 것보다 같은 이름을 사용하는 것이 해당 메소드가 어떤 기능을 가지고 있는지 기억하기 쉽다.
[오버로드 정의]
public class 클래스명 {
...
public void 메소드명(String str) { ... }
public void 메소드명(int num) { ... }
public void 메소드명(String str, int num) { ... }
public void 메소드명(int num, String str) { ... }
...
}
[예제] 같은 이름의 메소드를 오버로드 기능으로 정의하고 메소드를 각각 호출하기
package jokun.chap14;
class Computer1{
private String os;
private int memory;
public void setComputer(String os){
this.os = os;
System.out.println("OS는 " + os + "로 변경했습니다.");
}
public void setComputer(int memory){
this.memory = memory;
System.out.println("메모리는 " + memory + "GB입니다.");
}
public void setComputer(String os, int memory){
this.os = os;
this.memory = memory;
System.out.println("OS는 " + os + "이고 메모리는 " + memory + "GB로 변경했습니다.");
}
public void show(){
System.out.println("PS의 OS는 " + os + "입니다.");
System.out.println("메모리는 " + memory + "GB입니다.");
}
}
public class OverLoadMethod {
public static void main(String[] args) {
Computer1 com = new Computer1();
com.setComputer("Windows 11", 32);
com.show();
System.out.println("=========================");
com.setComputer("Windows 10");
com.show();
System.out.println("=========================");
com.setComputer(256);
com.show();
}
}
▽ 실행화면 ▽
# 생성자 오버로딩
생성자도 오버로딩이 가능하므로, 하나의 클래스에 여러 개의 생성자가 존재할 수 있다.
[생성자 오버로드]
class 클래스명 (타입 변수명, 타입 변수명…({
// 인스턴스 생성 시 수행될 코드,
// 주로 인스턴스 변수의 초기화 코드를 적는다.
}
[예제] 생성자 오버로딩하기
package jokun.chap14;
class Computer3{
private String os;
private int memory;
public Computer3(){
this.os = null;
this.memory = 0;
}
public Computer3(String os, int memory){
this.os = os;
this.memory = memory;
System.out.println("OS는 " + os + "이고 메모리는 「" + memory + "GB의 PC가 만들었습니다.");
}
public void show(){
System.out.println("PC의 OS는 " + os + "입니다.");
System.out.println("메모리는 " + memory + "GB입니다.");
}
}
public class OverLoadConstructor {
public static void main(String[] args) {
Computer3 com1 = new Computer3();
com1.show();
System.out.println("===============================================================");
Computer3 com2 = new Computer3("Windows 11",32);
com2.show();
}
}
▽ 실행 화면 ▽
[연습문제]
14-4. 연습문제
<질문1> 다음의 질문 ①~⑤에 대해 ○인가 ×로 대답하십시오.
① 클래스내에 같은 이름의 메소드를 정의할 수 있는 기능을 오버로드라고 한다. O
② 메소드는 오버로드할 수 있지만, 생성자는 할 수 없다. X
③ 오버로드 기능의 제약은 반환값의 형태 혹은 인수의 이름이 달라야 한다. X
④ 한 생성자에서 동일한 클래스 내에 정의된 다른 생성자를 호출할 수 있다. O
⑤ 한 생성자로부터 다른 생성자를 호출하는 경우, 기술 위치의 제약은 없다. X
<질문2> Books1.java 클래스에 이하의 사양을 가지는 2개의 생성자를, 오버로드를 이용해 정의해 주세요.
생성자 1
인수 없이 필드 변수 title에 null, price에 0을 설정합니다.
생성자 2
2 개의 인수 String 형의 title, int 형의 price 의 값을, 각각의 필드 변수에 설정한다
① 소스 폴더: javabasic/src
② 패키지: chap14Excercise
③ 이름: Books1
package chap14Excercise;
public class Books1 {
String title;
int price;
// 생성자1
//※여기에 생성자1처리를 정의함
// 생성자2
//※여기에 생성자2처리를 정의함
}
<질문3> 아래의 Books2 클래스는 생성자로부터 다른 생성자를 호출하고 있다. 이대로는 컴파일 에러가 되어 버리는 이유를 선택사항으로부터 선택해 주세요.
조건
① 생성자로부터 다른 생성자를 호출할 수 없기 때문에.
② 생성자에게 주는 인수가 잘못되어 있기 때문.
③ 2개의 생성자가 호출 무한 루프가 되어 있기 때문에.
④ 생성자가 호출하는 이름이 잘못되어 있기 때문.
⑤ 처리의 선두에 constructor 호출이 있기 때문에.
public class Books2{
String title;
int price;
// 생성자1
Books2() {
this("Window 11", 32);
this.title = null;
this.price = 0;
}
// 생성자2
Books2(String title, int price) {
this();
this.title = title;
this.price = price;
}
}
<질문4> Calc1 클래스 내에 아래 사양을 가지는 2개의 덧셈 메소드에 대해서, 오버로드 기능을 이용하여 정의해 주세요. 그 때의 메소드명은 addition으로 합니다.
메소드1
인수:int형 num1, num2 반환값 int형(num1+num2)
메소드2
인수: double 형 num1, num2 반환값 double 형 (num1+num2)
package chap14exercise;
public class Calc1 {
// 정수 값 두 개의 더하기 결과를 반환합니다.
※여기에 메소드 1의 정의를 기술한다
// 부동 소수점 숫자 두 개의 더하기 결과를 반환합니다.
※여기에 메소드 2의 정의를 기술한다
}
▽ 답 ▽
package jokun.chap14;
public class Calc1 {
public int addition(int num1, int num2){
return num1 + num2;
}
public double addition(double num1, double num2){
return num1 + num2;
}
}
<질문5> 아래 실행 결과가 되도록 ①~⑤의 공란을 채워 주십시오. Calc2 클래스에는 문제4에서 작성한 2개의 메소드와 같은 메소드가 정의됩니다.

package chap14Excercise;
class Calc2 {
// 정수값 2개를 더한 결과 리턴
// 여기에 메소드1의 정의를 기술함
// 부동소수점 2개의 데이터를 받음
}
public class Calc1 {
public static void main(String[] args){
①Calc2 calc = new ①;
②num1 = 10;
②num2 = 20;
System.out.println(num1 + " + " + num2 + " = " + calc.③);
④ num3 = 45.2;
④ num4 = 16.9;
System.out.println(num3 + " + " + num4 + " = " + calc.⑤);
}
}
▽ 답 ▽
package chap14Excercise;
class Calc2 {
// 정수값 2개를 더한 결과 리턴
// 여기에 메소드1의 정의를 기술함
// 부동소수점 2개의 데이터를 받음
}
public class Calc1 {
public static void main(String[] args) {
①Calc2 calc = new calc2;
int num1 = 10;
int num2 = 20;
System.out.println(num1 + " + " + num2 + " = " + calc.addition(num1,num2)
);
double num3 = 45.2;
double num4 = 16.9;
System.out.println(num3 + " + " + num4 + " = " + calc..addition(num3,num4));
}
}