article thumbnail image
Published 2020. 2. 28. 17:54

회사에 출근해서 업무를 시작하기 전에 제일 먼저 하는 일이 아마 책상 정리일 것이다.

커피를 내리는 경우도 있을 것이고, 컴퓨터 부팅을 시작하기도 할 것이다.

즉 어떤 일을 시작하기 전에 준비를 하게 되는데 이것을 다른 말로 초기화라고 한다.

객체 지향 프로그래밍도 초기화에 해당하는 기능이 제공되는데 이것을 생성자(constructor)라고 한다.

 

앞에서 살펴봤던 계산기 예제를 보자.

객체를 이용하기 위한 로직은 아래와 같다.

위의 예에서 메소드 setOprands의 값으로 10과 20을 지정했다.

이 값들은 객체 내부에서 인스턴스 변수 left와 right의 값으로 설정되어서 유지된다.

그런데 이 객체를 이용하기 위해서는 기억해야 할 것이 있다.

아래와 같이 메소드 setOprands를 호출하기 전에 sum과 avg를 호출한다면 원하는 결과를 얻을 수 없을 것이다.

 

이것은 객체 Calculator를 사용하기 위해서 사용자는 메소드 sum을 호출하기 전에 setOprands를 호출해야 한다는 것을 기억하고 있어야 한다는 것을 의미한다. 이러한 절차를 기억해야 한다는 것은 사용자 입장에서는 불편할 뿐 아니라 잘못된 사용으로 오류가 발생할 확률을 높이는 결과를 초래 할 수 있다.

 

절차를 따라야 하므로 사용자가 실수할 가능성이 있다.

인자를 주지 않으면 에러가 발생하기 때문에 사용자가 setOperand를 실행하지 않는 실수를 범할 가능성이 높다.


생성자

그래서 사용하는 것이 생성자(Constructor)이다. 아래와 같이 인스턴스가 생성될 때 left, right의 값을 입력하도록 강제한다면 어떨까?

위와 같이 Calculator의 사용방법을 변경하기 위해서는 아래와 같이 코드를 작성한다. (실행) 

package org.opentutorials.javatutorials.constructor;
 
class Calculator {
    int left, right;
 
    public Calculator(int left, int right) {
        this.left = left;
        this.right = right;
    }
 
    public void sum() {
        System.out.println(this.left + this.right);
    }
 
    public void avg() {
        System.out.println((this.left + this.right) / 2);
    }
}
 
public class CalculatorDemo1 {
 
    public static void main(String[] args) {
 
        Calculator c1 = new Calculator(10, 20);
        c1.sum();
        c1.avg();
 
        Calculator c2 = new Calculator(20, 40);
        c2.sum();
        c2.avg();
    }
 
}

7행에 아래와 같은 내용이 추가 되었다. Caculator라는 메쏘드, 이것이 바로 생성자이다.

생성자가 하는 역할은 이 클래스가 생성될 때

자동으로 클래스와 똑같은 이름을 가지고있는 생성자가 실행되도록 약속되어 있다.

이 생성자가 어떤 메쏘드보다 먼저 실행되도록 약속되어 있다.

 

그렇기 때문에 클래스와 같은 이름을 가지고 있는 어떠한 메쏘드를 정의해서

메쏘드에 로직을 채워넣게 되면

그 로직은 어떠한 메쏘드보다 먼저 실행돼서 그 객체가 가장 먼저 해야될 일, 다시말해서 초기화 작업을 하도록 할 수가 있다.

 

만약 우리가 객체를 생성할 때 클래스에 클래스와 똑같은 이름의 메쏘드가 없다면 

클래스와 똑같은 이름의 메쏘드를 자동으로 ! 만든다.

없으면 만들고 있으면 우리가 만든 것을 사용하게 된다.

 

class 와 같은 이름을 가지는 메쏘드 = 생성자

 

사실은 우리가 객체를 만들때

Calculator c1 = new Calculator(10,20);

Calculator는 클래스가 아니라 생성자이다.

인자를 주는 것은 이것이 생성자 라는 것을 더 명확하게 드러낸다.

인스턴스를 생성하는 자이다.

Calculator라는 클래스를 구체화시킨 구체적 제품인 인스턴스를 만들 수 있는 것이다.


생성자는 그 이름처럼 객체를 생성할 때 호출된다. 25행은 위의 생성자를 이용해서 객체를 생성하는 방법을 보여준다.

생성자 덕분에 Calculator 객체를 사용하기 위해서 사실상 반드시 필요한 작업이라고 할 수 있는 좌항(left)과 우항(right)의 값을 설정하는 과정을 객체 생성 과정에서 강제할 수 있게 되었다. 절차를 하나 줄인 것뿐이지만, 객체를 사용하기 위해서는 객체를 생성해야 한다는 사실은 기본적으로 숙지하고 있는 절차이기 때문에 이 절차에 필수적인 작업을 포함시킨다는 것은 중요한 의미를 갖게 된다.

 

생성자의 특징

생성자의 특징은 아래와 같이 정리할 수 있다.

  1. 값을 반환하지 않는다. 
    생성자는 인스턴스를 생성해주는 역할을 하는 특수한 메소드라고 할 수 있다. 그런데 반환 값이 있다면 엉뚱한 객체가 생성될 것이다. 따라서 반환 값을 필요로하는 작업에서는 생성자를 사용하지 않는다. 반환 값이 없기 때문에 return도 사용하지 않고, 반환 값을 메소드 정의에 포함시키지도 않는다.
  2. 생성자의 이름은 클래스의 이름과 동일하다.
    자바에서 클래스의 이름과 동일한 메소드는 생성자로 사용하기로 약속되어 있다.

 


생성자(Constructor)

 생성자는 new 연산자를 통해서 인스턴스를 생성할 때 반드시 호출이 되고 제일 먼저 실행되는 일종의 메소드(하지만 메소드와는 다르다.)이다. 생성자는 인스턴스 변수(필드 값 등)를 초기화 시키는 역할을 한다. 

생성자 선언 방법

 생성자를 선언하는 방법은 위에 내용과 같다. 클래스라는 부분은 생성자를 정의하는 클래스의 이름과 동일하게 적어줘야 한다. 빨간색으로 표시한 부분은 필수로 적어야 하는 내용은 아니다. public에 대한 내용은 나중에 다룰 예정이고 우선은 생성자를 선언할 때는 public을 적어주면 된다.

생성자 종류 및 사용

 위에서 생성자 선언하는 방법을 알아보았다. 인스턴스를 생성할 때 반드시 생성자를 호출한다고 하였다. 그런데 지금까지는 생성자를 정의하지 않았는데 어떻게 호출이 된 것일까? 그 이유는 클래스를 정의할 때 생성자를 생략하면 컴파일러가 자동적으로 기본 생성자(Default Constructor)를 생성하여 주기 때문이다. Default 생성자란 "public 클래스(){ }"를 의미한다. 소스 코드를 통해서 알아보자.

public class ConstructorEx01 {
//	public ConstructorEx01(){ } // Default Constructor 자동 생성
	
	public static void main(String[] args) {
		ConstructorEx01 ce = new ConstructorEx01(); // 인스턴스 생성 및 생성자 호출
	}
}

 위의 내용처럼 인스턴스를 생성할 때 생성자를 호출한다. 생성자를 생략하면 주석 처리된 부분이 자동으로 생성된다. 이번에는 기본 생성자를 직접 정의하는 내용을 알아보자.

public class ConstructorEx01 {
	public ConstructorEx01(){ 
		System.out.println("생성자 호출 성공");
	}
	
	public static void main(String[] args) {
		ConstructorEx01 ce = new ConstructorEx01(); // 인스턴스 생성 및 생성자 호출
	}
}

처음 예제와 비교하면 생성자를 직접 정의하였고 생성자 내부에 소스코드 한 줄을 추가하였다. 결과는 "생성자 호출 성공"이 출력된다.

생성자를 선언할 때 매개변수를 괄호 안에 가질 수 있다고 하였고 그것에 대한 예제를 살펴보자.

public class ConstructorEx02 {
	public ConstructorEx02(String a){ // a = 사용자 정의
		System.out.println(a + " 생성자 호출 성공");
	}
	
	public static void main(String[] args) {
		ConstructorEx02 ce = new ConstructorEx02("사용자 정의"); // 매개변수를 갖는 생성자 호출
//		ConstructorEx02 ce2 = new ConstructorEx02(); // 컴파일 에러
	}
}

  매개변수를 갖는 생성자를 정의하였고 main 메소드에서 생성자를 호출하였다. 결과는 "사용자 정의 생성자 호출 성공"이 출력된다. 그다음 줄의 주석 처리된 부분은 기본 생성자를 호출하지만 컴파일 에러가 발생된다. 그 이유는 사용자가 정의한 생성자가 있어서 Default 생성자를 더 이상 자동으로 만들어주지 않기 때문이다. 컴파일 에러를 해결하려면 아래와 같이 작성하면 된다.

public class ConstructorEx03 {
	public ConstructorEx03(){
		System.out.println("생성자 호출 성공");
	}
	public ConstructorEx03(String a){ // a = 사용자 정의
		System.out.println(a + " 생성자 호출 성공");
	}
	
	public static void main(String[] args) {
		ConstructorEx03 ce = new ConstructorEx03("사용자 정의"); // 매개변수를 갖는 생성자 호출
		ConstructorEx03 ce2 = new ConstructorEx03(); // 기본 생성자 호출
	}
}

 기본 생성자를 추가하였고 정상적으로 결과가 출력된다. 참고로 생성자의 매개변수를 다르게 지정하여 정의하는 것을 생성 오버로딩이라고 한다.(오버로딩에 관한 내용은 별도 포스팅 참고)

 생성자의 역할은 인스턴스를 초기화 시킨다고 하였는데 무엇을 의미하는지 소스코드를 통해 알아보자.

class CalculatorEx {
	// 필드변수 선언
	int a;
	int b;

	public CalculatorEx() { // 기본 생성자
		// 필드변수 초기화
		a = 10;
		b = 20;
	}

	public CalculatorEx(int num1, int num2) { // 생성자 오버로딩
		// 매개값 이용 필드변수 초기화
		a = num1;
		b = num2;
	}

	public void sum() { // 메소드
		System.out.println("합계 : " + (a + b));
	}
}

public class ConstructorEx04 {
	public static void main(String[] args) {
		CalculatorEx cc = new CalculatorEx();
		cc.sum(); // 결과 : 30
		CalculatorEx cc2 = new CalculatorEx(0, 10);
		cc2.sum(); // 결과 : 10
	}
}

별도의 클래스를 하나 정의하였고 필드변수(int a, int b)를 선언하였다. 기본 생성자매개변수를 갖는 생성자를 정의하고 메소드에서 합을 구하는 코드를 추가하였다. main 메소드에서 인스턴스를 생성하면서 생성자를 호출하였고 호출된 생성자에 의해 필드변수가 초기화되었다. 그리고 인스턴스로 메소드를 호출하여 값을 출력한다. 

 

생성자의 특징(메소드와의 차이)

 앞에서 설명한 것처럼 생성자는 반드시 클래스명과 동일하게 정의하여야 한다. 생성자 앞에는 접근 제어자(public 등)만 올 있다.(메소드는 static과 같은 수식어를 작성할 수 있다.) 반환값이 없으므로 void나 자료형을 작성할 수 없다.(메소드는 void나 자료형이 있어야 한다.) 그 외에도 상속이 되지 않거나 하는 차이가 있지만 이 내용에 대해서는 상속 관련 포스팅에서 알아보도록 하겠다.

 

'📌 java > java' 카테고리의 다른 글

java - 상속과 생성자  (0) 2020.03.03
java - 상속  (0) 2020.03.02
java - 유효 범위  (0) 2020.02.26
java - 클래스 멤버와 인스턴스 멤버  (0) 2020.02.25
java - 클래스와 인스턴스 (2020/02/20)  (0) 2020.02.20
복사했습니다!