이것이 자바다 6장 - 생성자

오늘·2021년 3월 3일
0

Java

목록 보기
10/42

생성자(Constructor)

  • 용도 : 객체화 할 때 자동 호출되어, 실행되면 초기화하는 것이 목적
  • 클래스의 생성자를 호출
  • 생성자를 사용자가 만들지 않으면 컴파일러가 기본 생성자를 자동으로 만들어 준다
    (→ 1개라도 명시적 생성자가 있다면 기본 생성자는 만들어지지 않는다)

-생성자를 실행시키지 않고는 클래스로부터 객체를 만들 수 없다
-new 연산자와 같이 사용되어 클래스로부터 객체를 생성할 때 호출되며, 객체의 초기화를 담당한다

(객체 초기화 : 필드를 초기화하거나, 메소드를 호출해 객체를 사용할 준비하는 것을 말한다.)


생성자 종류

생성자 종류
1. 기본 생성자 : 클래스명(){ }
2. 명시적 생성자 : 클래스명(자료형 변수형, 자료형 변수형){ }


기본 생성자

모든 클래스에는 생성자가 반드시 존재하며, 하나 이상 가질 수 있다

Person(){

}
// 중괄호가 비어있는 기본 생성자이다
// 생성자 선언이 따로 없다면 컴파일러는 이러한 생성자를 자동 추가한다.

기본 생성자에 초기화 내용을 넣을 수도 있다

public class Ch06_1 {

	// 필드 : 학변, 이름, 전공, 지도교수코드, 점수
	// 용도 : 자료를 변수에 넣기
	String number = null; // 학번
	String name = null; // 이름
	String dept = null; // 전공
	int teacherCode = 0; // 지도교수 코드
	double score = 0; // 점수
	boolean gen;
    
    	Ch06_1(){
        // 기본 생성자에 값 넣기
		number = "2021";
		name = "오늘";
		dept = "computer";
		teacherCode = 88;
		score = 98;
		gen = true;
	}
}
// main
Ch06_1 student = new Ch06_1();
System.out.println(student.number + ", "+student.name);

실행 결과

필드에 변수 선언해줄때 number와 name은 null로 초기화와 동시에 선언해주었음에도 main에서 출력해보면 기본 생성자에 넣어놓은 값으로 출력되는 것을 알 수 있다.


명시적 생성자 선언

명시적으로 생성자를 선언하는 이유는 객체를 조금 더 다양하게 초기화하기 위해서이다.

클래스(매개변수 선언,){
	// 객체의 초기화 코드
}

매개변수는 new 연산자로 생성자를 호출할 때 외부 값을 생성자 블록 내부로 전달하는 역할을 한다. 예를 들어 메인에서 Ch06_1 생성자를 호출할 때 년도와 이름이라는 두개의 값을 제공한다고 보자

// main
Ch06_1 student2 = new Ch06_1("1988", "한태주");

이런 식으로 작성할 수 있다. 두 매개는 모두 String 타입이고, 이러한 매개값을 받을 수 있으려면

public class Ch06_1 {
	Ch06_1(String num, String na){}
}

이런식으로 작성해줘야한다. String을 두 개 받을 수 있도록 작성해주는 것이다.

// main에서 전해준 매개변수
// Ch06_1 ex3 = new Ch06_1(5.5, true);

// 저 매개변수를 받기위한 작성
public class Ch06_1 {	
    Ch06_1(double num, boolean gender){}
}

이 경우에는 double 타입과 boolean 타입의 매개변수 제공했고, 이를 받기 위하여 동일한 타입이 포함되도록 작성한 것이다.


필드 초기화

  • 클래스로부터 객체가 생성될 때 필드는 기본 초기값으로 자동 설정된다. 만약 다른 값으로 초기화를 하고 싶다면 두 가지 방법이 있다.
  • 일단 당연하지만 두 방법은 다르다
    -메소드 동작 : 호출할 때마다 수행, 여러번 수행해야 하는것
    -생성자 동작 : 객체생성 할 때 수행, 한번 수행해야 하는것(그래서 초기값 세팅시 사용)
  1. 필드를 선언할때 초기값을 준다.
(1)
public calss Nation {
	String one = "대한민국";


(2)
Nation na = new Nation();
Nation na1 = new Nation();
//na와 na1에는 모두 "대한민국" 이 저장되어있다.
}
  1. 생성자에서 초기값을 준다.
    이 방법은 외부에서 제공되는 다양한 값들로 초기화 되어야 할 때 사용된다. 사람의 정보에서 '이름'과 '주민번호'는 클래스 작성시 (모두 같은) 초기값을 주는 것이 아니라 객체가 생성되는 시점에 다양한 값을 받아야 하는 것이다.
(1)
public class Person{
	String nation = "대한민국";
    	String name;
        String ssn;
        // 나라는 동일하게 대한민국으로 설정한다.
        // 이름과 주민번호는 다양하게 값을 받을 것이기에 선언만 해준다.
        
        // 생성자
        public Person(String na, String sn){
        	name = na;
            	ssn = sn;
        }
}




(2)
Nation na = new Nation("감자", "020103-1357911);
Nation na1 = new Nation("고구마", "020513-4386923);
// 이 코드에서 감자 와 고구마는 매개변수 na를 통해 전달되고
// 번호는 sn을 통해 ssn에 전달된다
// 이 값들은 각각 name ssn 필드의 초기값으로 사용된다
  • Nation 생성자의 배개 변수의 이름을 na, sn이라고 줬지만, 너무 짧으면 코드의 가독성이 좋지 않기 때문에 가능하면 초기화시킬 필드의 이름과 비슷하거나 동일한 이름을 사용할 것을 권한다.
  • 관례적으로 필드와 동일한 이름을 갖는 매개 변수를 사용한다.
    -하지만 이 경우 필드와 매개변수의 이름이 동일하기 때문에 매개 변수의 사용 우선순위가 높아 제대로 된 값이 안나올 수 있다.
    -따라서 필드 앞에 this.을 붙인다. 이는 참조변수로 필드를 사용하겠다 말하는 것이다.
public class Person{
	String nation = "대한민국";
    	String name;
        String ssn;
        // 나라는 동일하게 대한민국으로 설정한다.
        // 이름과 주민번호는 다양하게 값을 받을 것이기에 선언만 해준다.
        
        // 생성자
        public Person(String name, String ssn){
        	this.name = name;
            	this.ssn = ssn;
        }
}


// this = 자기 자신의 멤버필드에 선언된 변수임을 표시해주는 것
// 자기 클래스 속 '필드'에 있는 멤버이다 를 표시해주는 것
// 생성자 속 매개변수의 변수명이 같아도 사용할 수 있게끔 해주는 그런것

생성자 오버로딩(Overloading)

매개 변수를 달리하는 생성자를 여러 개 선언하는 것을 말한다.
위와 같이 클래스의 이름은 같으면서 받는 매개 변수만 다른 것

public class Over{
	Over(int num, String name){ ... }
    Over(String name, int num){ ... }
    
// 같은 매개값이더라도 순서가 다르면 선언 가능
// Ch06_1(String number, String name){} // 가장 먼저 선언된 생성자
// Ch06_1(String number, String name){} // ←불가능
// Ch06_1(String name, String number){} // ←가능
}

생성자 오버로딩 시 주의할 점은 매개 변수의 타입과 개수 그리고 선언된 순서가 똑같을 경우, 매개변수의 이름만 바꾼다고 생성자 오버로딩이라 볼 수 없다.

Over(int num, String name){ ... }
Over(int nu, String na){ ... }
// 안된다

생성자가 오버로딩되어있을 경우, new 연산자로 생성자를 호출할 때 제공되는 매개 값의 타입과 수에 의해 호출될 생성자가 결정된다.

Ch06_1 ex3 = new Ch06_1(5.5, true);
// 호출될 생성자
// Ch06_1(double num, boolean gender){ ... }

Ch06_1 ex4 = new Ch06_1("수학과", "홍길동", false);
// 호출될 생성자
// Ch06_1(String dep, String nam, boolean gend){ ... }

// 생성자 호출 자료와 생성자 정의 매개변수 자료는  1 대 1 대응
// 생성자는 매개변수의 자료형과 갯수를 달리한다면 여러개 만들기 가능
// 생성자 오버로딩(생성자를 매개변수 타입을 다르개 해서 재사용하는 것을)
// 1개라도 명시적 생성자가 있다면 기본 생성자는 만들어지지 않는다.

생성자 안에서 생성자를 호출할 수 있어요

클래스( 매개변수선언, ... ) {
	this(매개변수, ... ,, ...);
    	실행문
}

생성자 오버로딩이 많아질 경우 생성자 간 중복 코드가 발생할 수 있다. 이 경우 필드 초기화 내용은 한 생성자에 집중적으로 작성하고 나머지 생성자는 초기화 내용을 가지고 있는 생성자를 호출하는 방법으로 개선할 수 있다.

Student(String name){
	this.name = name;
    	this.number = 13;
        this.age = 14;
}

Student(String name, int number){
	this.name = name;
    	this.number = number;
        this.age = 14;
}

Student(String name, int number, int age){
	this.name = name;
    	this.number = number;
        this.age = age;
}

한눈에 봐도 중복되는 부분이 보일 것이다. 세 개의 생성자 내용이 비슷하므로 앞 두개의 생성자에서 this()를 사용해 마지막 생성자를 호출할 수 있도록 수정하면 중복 코드를 최소화 할 수 있지 않을까

Student(String name){
	this(name, 13, 14);
    	// 넣을 값을 넣어 마지막 생성자를 호출해 처리
}
Student(String name, int number){
	this(name, number, 14);
}
Student(String name, int number, int age){
	this.name = name;
    	this.number = number;
        this.age = age;
}

0개의 댓글