관리 메뉴

나만을 위한 블로그

[JAVA] 생성자란? 본문

JAVA

[JAVA] 생성자란?

참깨빵위에참깨빵_ 2020. 10. 7. 20:27
728x90
반응형

생성 : 사물이 생겨남, 사물이 생겨 이뤄지게 함 / 생성자 : 어떤 것을 만들어내는 사람?

자바의 생성자 : 객체 생성 시 항상 실행되는 것으로 객체를 초기화하기 위해 맨 처음 실행되는 메서드. 객체의 속성에 대한 초기값을 설정하는 데 사용된다.

 

A 클래스에서 B 클래스에 있는 메서드나 변수를 사용하려면 어떻게 해야 할까?

B 클래스의 요소들을 쓸 수 있도록 B 클래스의 객체를 생성하면 된다.

예를 들어서 Person이라는 클래스를 만들고, 이 클래스의 전역변수로 나이와 이름을 받는 변수를 만든뒤 두 값을 받아서 출력하는 메서드를 Person 클래스에 만든다고 하자.

그럼 아래와 같은 형태가 될 것이다.

 

public class Person {
	
	int age;
	String name;

	public Person(int age, String name) {
		this.age = age;
		this.name = name;
	}
	
	public void print()
	{
		System.out.println("이름 : " + name + ", 나이 : " + age);
	}
	
}

그리고 다른 클래스에서 이 클래스에 있는 print()를 사용하려면 Person 클래스의 객체를 생성해야 한다.

객체 생성은 아래와 같이 한다.

 

Person person = new Person(20, "김철수");

여기서 new Person(20, "김철수"); 부분이 바로 생성자다. () 안에 들어있는 20과 김철수라는 문자열로 객체의 속성값을 초기화해서 객체를 만든다.

이렇게 쓴 이유는 생성자 안에서 int age, String name을 받아서 Person 클래스의 전역변수 age, name에 각각 값을 전달하도록 했기 때문이다.

만약 객체 생성 시 값을 안 넣을 거라면 이렇게 만들면 된다.

 

Person person = new Person();

그런데 지금 코드를 저렇게 수정하면 컴파일 에러가 발생한다.

Add arguments to match 'Person(int, String)' 이라는 에러다. Person(int, String)이라고 미리 정의했던 생성자에 맞게 값을 넣으라는 뜻이다. 그런데 난 값을 안 넣고 객체를 만들고 싶다. 그럼 어떻게 해야 할까?

바로 디폴트 생성자를 만들면 된다. 디폴트 생성자는 인자가 하나도 없고 아무 기능도 없이 객체만 찍어내는 생성자를 말한다.

 

public class Person {
	
	int age;
	String name;

	public Person(int age, String name) {
		this.age = age;
		this.name = name;
	}
	
	// 디폴트 생성자
	public Person() {}
	
	public void print()
	{
		System.out.println("이름 : " + name + ", 나이 : " + age);
	}
	
}

저장하고 메인 클래스로 돌아가보면 컴파일 에러가 사라져 있다.

 

위 코드처럼 () 안에 어떤 인자도 넣지 않고 중괄호 안에도 어떤 코드도 넣지 않는다면 디폴트 생성자가 생성된 것이다. 또한 생성자는 한 클래스 안에 여러 개를 만들 수 있다. 위처럼 클래스를 만들어도 어떤 컴파일 에러도 뜨지 않는다.

이렇게 한 클래스 안에 생성자를 여럿 만드는 것을 생성자 오버로딩이라고 한다. 그런데 막 만든다고 전부 생성자 오버로딩인 건 아니고, 생성자 오버로딩이 성립되는 조건이 몇 가지 있다.

  • 생성자 오버로딩은 같은 클래스 안에서만 이뤄져야 한다.
  • 생성자 안에 선언된 인자(=매개변수) 타입, 순서, 개수가 달라야 한다.

위의 Person 클래스에서 생성자 오버로딩을 구현한다면 아래와 같이 할 수 있다.

 

public class Person {
	
	int age;
	String name;

	public Person(int age, String name) {
		this.age = age;
		this.name = name;
	}
	
	// 디폴트 생성자
	public Person() {}
	
	// 생성자 오버로딩
	public Person(int age) {
		this.age = age;
	}
	
	public Person(String name) {
		this.name = name;
	}
	
	public void print()
	{
		System.out.println("이름 : " + name + ", 나이 : " + age);
	}
	
}

 

첫 번째 생성자와 두 번째의 디폴트 생성자를 제외하고 int age만을 받아서 객체를 만드는 생성자, String name만을 받아서 객체를 만드는 생성자를 만들었다.

 

이제 디폴트 생성자가 아닌 원래 생성자에 20과 김철수라는 값을 넣고 print()를 호출해서 프로그램을 실행시켜보자.

 

 

콘솔창에 이런 결과가 나오는 걸 볼 수 있다.

그럼 이 print()는 생성자 안에 값을 넣어야지만 호출할 수 있을까? 디폴트 생성자로 person 객체를 생성한 뒤 print()를 실행시키면 아래와 같은 결과가 나온다.

 

 

메서드가 실행은 된다. 하지만 생성자 안에 어떤 값도 넣지 않았기 때문에 문자열이 들어가야 하는 부분은 null, int가 들어가야 하는 부분은 0으로 출력되는 걸 볼 수 있다.

그럼 생성자 오버로딩을 통해 만든 생성자로도 객체를 만들고 print()를 호출해보자.

 

 

int age만 받는 생성자로 생성한 객체로 print()를 호출하면 나이만 찍히고, String name만 받는 생성자로 생성한 객체로 print()를 호출하면 이름만 찍혀 나오는 걸 볼 수 있다.

그런데 이 생성자 오버로딩은 왜 필요할까? 그냥 생성자 하나만 띡 만들어놔도 쓰는 데 불편함은 없지 않나?

생성자 오버로딩이 필요한 이유는 같은 기능의 메서드를 만들 때 인자, 즉 입력값을 다양하게 받기 위해서다.

프로그램의 몸집이 커질수록 메서드는 많아지기 마련이다. 이 때 같은 기능을 수행하는 메서드를 인자값에 따라 이름을 다르게 정의하면 복잡하고 관리하기 빡셀 것이다. 이 때 생성자 오버로딩을 사용하거나 생각해 볼 필요가 생긴다.

 

아래는 생성자의 특징을 정리한 것이다.

 

  • 생성자 이름은 클래스명과 동일하다. 대소문자도 모두 똑같다.
  • 생성자는 리턴값이 없다. void도 사용하지 않는다.
  • 객체 생성 시 하나의 생성자만 호출된다.
  • 생성자를 통해서 생성자가 있는 클래스의 전역변수 값을 초기화할 수 있다.
  • 하나의 클래스에는 인자와 자료형이 틀린 생성자를 여러 개 만들 수 있다. 이걸 생성자 오버로딩이라고 한다.
반응형
Comments