생성자 -필요한 이유
this
package construct;
public class MemberInit {
String name;
int age;
int grade;
//추가
void initMember(String name, int age, int grade) {
this.name = name;
this.age = age;
this.grade = grade;
}
}
package construct;
public class MethodInitMain3 {
public static void main(String[] args) {
MemberInit member1 = new MemberInit();
member1.initMember("user1", 15, 90);
MemberInit member2 = new MemberInit();
member2.initMember("user2", 16, 80);
MemberInit[] members = {member1, member2};
for (MemberInit s : members) {
System.out.println("이름:" + s.name + " 나이:" + s.age + " 성적:" +
s.grade);
}
}
}
initMember()는 Member에 초기값 설정 기능을 제공하는 메서드이다.
initMember(String name...) 의 코드를 보면 메서드의 매개변수에 정의한 String name 과 Member 의 멤 버 변수의 이름이 String name 으로 둘다 똑같다. 나머지 변수 이름도 name , age , grade 로 모두 같다.
멤버 변수와 메서드의 매개변수의 이름이 같으면 둘을 어떻게 구분해야 할까?
- 이 경우 멤버 변수보다 매개변수가 코드 블럭의 더 안쪽에 있기 때문에 매개변수가 우선순위를 가진다. 따라서 initMember(String name,...) 메서드 안에서 name 이라고 적으면 매개변수에 접근하게 된다.
- 멤버 변수에 접근하려면 앞에 this. 이라고 해주면 된다. 여기서 this 는 인스턴스 자신의 참조값을 가리킨다
this.name = name; //1. 오른쪽의 name은 매개변수에 접근
this.name = "user"; //2. name 매개변수의 값 사용
x001.name = "user"; //3. this.은 인스턴스 자신의 참조값을 뜻함, 따라서 인스턴스의 멤버 변수에 접근
this 제거
this를 제거하면 name은 둘다 매개변수를 뜻하게 된다. 따라서 멤버변수의 값이 바뀌지 않는다.
name = name
정리
- 매개변수의 이름과 맴버 변수의 이름이 같은 경우 this 를 사용해서 둘을 명확하게 구분해야 한다.
- this 는 인스턴스 자신을 가리킨다
this 생략
package construct;
public class MemberThis {
String nameField;
void initMember(String nameParameter) {
nameField = nameParameter;
}
}
this는 생략할 수 있다. 이 경우 변수를 찾을 때 가까운 지역변수(매개변수도 지역변수다)를 먼저 찾고 없으면 그 다음 멤버 번수를 찾는다. 멤버 변수도 없으면 오류 발생
생성자
필요한 이유
프로그래밍을 하다 보면 객체를 생성하고 이후에 바로 초기값을 할당해야 하는 경우가 많다. 따라서 앞서 initMember()와 같은 메서드를 매번 만들어야 한다. 그래서 대부분 객체 지향 언어는 생성하자마자 즉시 필요한 기능을 좀 더 편리하게 수행할 수 있도록 생성자라는 기능을 제공한다.
package construct;
public class MemberConstruct {
String name;
int age;
int grade;
MemberConstruct(String name, int age, int grade) {
System.out.println("생성자 호출 name=" + name + ",age=" + age + ",grade=" +
grade);
this.name = name;
this.age = age;
this.grade = grade;
}
}
이 부분이 생성자이다.
MemberConstruct(String name, int age, int grade) {
System.out.println("생성자 호출 name=" + name + ",age=" + age + ",grade=" +
grade);
this.name = name;
this.age = age;
this.grade = grade;
}
생성자는 메서드와 비슷하지만 다음과 같은 차이가 있다.
- 생성자의 이름은 클래스 이름과 같아야 한다. 따라서 첫글자도 대문자로 시작한다.
- 생성자는 반환 타입이 없다. 비워두어야 한다.
- 나머지는 메서드와 같다.
생성자 호출
생성자는 인스턴스를 생성하고 나서 즉시 호출된다. 생성자를 호출하는 방법은 new 명령어 다음에
생성자 이름과 매개변수에 맞추어 인수를 전달하면 된다.
new 생성자이름(생성자에 맞는 인수 목록)
new 클래스이름(생성자에 맞는 인수 목록)
참고로 new 키워드를 사용해서 객체를 생성할 때 마지막에 괄호 () 도 포함해야 하는 이유가 바로 생성자 때문이다. 객 체를 생성하면서 동시에 생성자를 호출한다는 의미를 포함한다.
생성자 장점
1.중복호출 제거
생성자가 없었을때는 생성 직후에 어떤 작업을 수행하기 위해 메서드를 직접 한번 더 호출해야 했다.
생성자 덕분에 객체를 생성하면서 동시에 생성 직후에 필요한 작업을 한번에 처리할 수 있게 되었다.
//생성자 등장 전
MemberInit member = new MemberInit();
member.initMember("user1", 15, 90);
//생성자 등장 후
MemberConstruct member = new MemberConstruct("user1", 15, 90);
제약 - 생성자 호출 필수
initMember(...)를 실수로 호출하지 않으면 어떻게 될까? 이 메서드를 실수로 호출하지 않아도 프로그램을 작동한다. 하지만 데이터가 없는 상태로 프로그램이 동작하게 된다. 만약 이 값들을 필수로 입력해야한다면, 시스템에 큰 문제가 발생할 수 있다.
생성자의 진짜 장점은 객체를 생성할 때 직접 정의한 생성자가 있다면 직접 정의한 생성자를 반드시 호출해야 한다.
생성자를 메서드 오버로딩처럼 여러개 정의할 수 있는데, 이 경우 하나만 호출하면 된다.
기본생성자
- 매개변수가 없는 생성자를 기본 생성자라 한다.
- 클래스에 생성자가 하나도 없으면 자바 컴팡리러는 매개변수가 없고, 작동하는 코드가 없는 기본 생성자를 자동으로 생성해준다.
- 생성자가 하나라도 있으면 자바는 기본 생성자를 만들지 않는다.
참고: 자바가 자동으로 생성해주는 기본 생성자는 클래스와 같은 접근 제어자를 가진다. public이면 public으로 가짐
생성자 - 오버로딩과 this()
package construct;
public class MemberConstruct {
String name;
int age;
int grade;
MemberConstruct(String name, int age) {
this(name, age, 50); //변경
}
MemberConstruct(String name, int age, int grade) {
System.out.println("생성자 호출 name=" + name + ",age=" + age + ",grade=" +
grade);
this.name = name;
this.age = age;
this.grade = grade;
}
}
생성자를 오버로딩 한 덕분에 성적 입력이 꼭 필요한 경우에는 grade 가 있는 생성자를 호출하면 되고, 그렇지 않은 경 우에는 grade 가 없는 생성자를 호출하면 된다. grade 가 없는 생성자를 호출하면 성적은 50 점이 된다.
this() 규칙
- this() 생성자 코드의 첫줄에만 작성할 수 있다.
- this() 를 사용하면 생성자 내부에서 다른 생성자를 호출할 수 있다. 이부분을 잘 활용하면 중복제거 가능