Backend/JAVA

[JAVA] JAVA 프로그래밍 기초 교육 : 생성자 & 오버로드

JOKUN 2022. 5. 25. 20:09

교재 : 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));
    }
}