JAVA 2011. 6. 13. 01:03
앞에서 본 GoodsStock 클래스를 객체를 생성할 때 필드 값을 넘겨줄 수 있다면 편리할 

것 같다. 다음 방법을 보자

obj = new GoodsStock("52135" , 200);

이렇게 넘겨준 두 값이 각각 goodsCode 필드와 stockNum 필드에 각각 대입된다면 

훨씬 깔끔해 질 것이다. 

그렇다면 방법이 무엇일까?  앞서 만든 GoodsStock 클래스로는 안된다. 이럴때 

사용하는 것이 생성자이다. 생성자에 대하여 알아보자

생성자란?

대게의 경우 객체를 생성하고 나서 할 일은 객체마다 고유한 데이터 값을 필드에

저장하는 것이다. 그런일은 대게 동일한 패턴으로 이루어지기 때문에 객체를 

생성할 때 마다 동일한 로직을 계속 사용하여야 하는데 이는 비효율적이다.

그래서 자바에서는 객체가 생성되고 나서 해야 할 일을 클래스안에 써두고, 모든 객체들이

그 로직을 이용해서 초기화 작업을 할 수 있도록 만들어 두었다. 그 부분이 바로

생성자(Constructor) 라고 한다.

생성자에는 메소드처럼 파라미터를 넘겨줄 수 있다. 예를 들어 앞서 했던 

StringBuffer 객체를 생성할 때 괄호 안에 쓴 ("Hey, Java") 라는 문자열이 바로 생성자에

넘겨지는 파라미터이다. 

obj = new StringBuffer("Hey, Java");

우리가 만든 GoodsStock 클래스에도 생성자가 있다면 위에 말했듯 파라미터로 넘겨줄 수 있다.

이렇게 쓰여진 파라미터는 생성자가 호출되면 생성자의 파라미터 변수를 통해 전달된다.

그렇기 때문에, 매소드의 파라미터와 같이 받는쪽의 파라미터의 타입, 수 , 순서 와 보내는 쪽의 

타입, 수 , 순서가 맞아야 한다. GoodsStock에선 다음과 같이 되야 한다.

class GoodsStock {
String goodsCode;
int stockNum;
GoodsStock(String code, int num ){
goodsCode = code;
stockNum = num;
}
void addStock(int amount){
stockNum += amount;
}
int subtractStrock(int amount){
if(stockNum < amount)
return 0;
stockNum -= amount;
return amount;
}
}

위와 같이 클래스와 같은 이름의 생성자가 있다.

그리고 뒤에 String형 과 int 형을 받는다, 보낼 때도 이 타입과 순서를 지켜야한다. 물론 수도

생성자를 보면 메소드와 비슷한 형태이다, 하지만 생성자 특유의 특징이 있는데 그것은

생성자는 리턴타입이 없어야 하고 클래스이름과 같아야한다.

그럼 GoodsStock 클래스에 있는 생성자를 이용해 객체를 만들어보자.

public class classExample {
public static void main(String args[]){
GoodsStock obj;
obj = new GoodsStock("52135",200);
System.out.println("상품 코드" + obj.goodsCode);
System.out.println("재고 수량" + obj.stockNum);
obj.subtractStrock(201);
System.out.println("상품 코드" + obj.goodsCode);
System.out.println("재고 수량" + obj.stockNum);
}
}

이런식으로 생성자를 호출하면 코드도 한결 간결해진다. 앞서 사용했던 

obj.goodsCode="52135";
obj.stockNum = 200;

이 두 줄이 없어졌기 때문이다.

둘 이상의 생성자를 갖는 클래스
 

경우에 따라서는 한 클래스 안에 하나의 생성자만 선언하는 것으로는 충분치 않을 때가

있다. 예를 들어 인터넷 사이트의 가입자 정보를 표현하는 다음과 같은 클래스를 선언해야

한다고 가정해보자.

[이름]
가입자 정보 클래스

[데이터]
이름
아이디
패스워드
전화번호
주소

[기능]
패스워드를 바꾼다
전화번호를 등록한다
주소를 등록한다


그런데 어떤 가입자는 이름, 아이디, 패스워드만 입력하고, 어떤 가입자는 전화번호와 주소까지

입력한다면, 어떤생성자를 만들어야 할까? 5개를 다 받는 생성자를 만들어야할지,, 고민된다.

방법은 그 두 상황의 생성자를 만들어 놓으면 된다.

class SubscriberInfo {
String name, id, password;
String phoneNo, address;
SubscriberInfo(String name, String id, String password){
this.name = name;
this.id = id;
this.password = password;
}
SubscriberInfo(String name, String id, String password, 
String phoneNo, String address){
this.name = name;
this.id = id;
this.password = password;
this.phoneNo = phoneNo;
this.address = address;
}
void changePassword(String password){
this.password = password;
}
void setPhoneNo(String phoneNo){
this.phoneNo = phoneNo;
}
void setAddress(String address){
this.address = address;
}
}

소스를 보면 첫번째 생성자는 파라미터를 이름, 아이디, 패스워드 이렇게 세개를 받는다.

각각 파라미터로 넘어오는 족족 필드에 파라미터를 넣어주고있다.

필드 앞에 this. 를 붙이는 이유는 파라미터 변수와 필드명이 같을 때 필드이름 앞에

this를 붙여 구분을 주는 것이다
. 필드명과 파라미터명이 다르면 필요없다.

두번째 생성자는 이름, 아이디, 비밀번호, 전화번호, 주소 모두를 받고 있다. 

이제 객체를 생성하는 소스를 보자.

public class constrExam {
public static void main(String args[]){
SubscriberInfo obj1, obj2;
obj1 = new SubscriberInfo("포스팅잉여", "fool", "1234");
obj2 = new SubscriberInfo("졸려라", "gotosleep", "1234", "010-3104-xxxx", "경기도 의정                                                       부시 의정부동 푸르미텔 20x호..");
printSubscriberInfo(obj1);
printSubscriberInfo(obj2);
}

static void printSubscriberInfo(SubscriberInfo obj) {
System.out.println("이름 : " + obj.name);
System.out.println("아이디 : " + obj.id);
System.out.println("비밀번호 : " + obj.password);
System.out.println("전화번호 : " + obj.phoneNo);
System.out.println("주소 : " + obj.address);
System.out.println();
}
}

먼저 클래스를 선언하는데 두가지 생성자를 호출하기 때문에 클래스 객체도 두개를 써준다.

obj1 엔 이름, 아이디, 비밀번호를 obj2 엔 이름, 아이디, 비밀번호, 전화번호, 주소 모두를 

넘겨준다. 이렇게 하고 실행을 하면 SubscriberInfo클래스의 필드에 파라미터로 넘어가는

데이터가 차곡차곡 들어갈 것이다. 그러고 printSubscriberInfo 라는 메소드를 만들어

각각 출력 하게 했다. printSubscriberInfo에 파라미터로 클래스 객체를 넘겨서 우선 

obj1 과 obj2 를 new SubscriberInfo 해서 데이터를 넣고 printSubscriberInfo에 

obj1, obj2 를 파라미터로 넘긴다면 그 안에 들어간 데이터들이 쭉 찍혀 나올 것이다. 

나는 초보자라 매소드하나 만드는게 큰맘먹고 생각 많이 해서 만들어야 할 정도로 

복잡하고 어려운 것이 었는데 이 책에선 단지 출력값 뿌리는데에 사용하고있다.. 

대단한것 같다.. 아직 멀었나보다. 

각설하고 이 프로그램을 실행 시키면 뭐가나오는지 보자.

이름 : 포스팅잉여
아이디 : fool
비밀번호 : 1234
전화번호 : null
주소 : null

이름 : 졸려라
아이디 : gotosleep
비밀번호 : 1234
전화번호 : 010-3104-xxxx
주소 : 경기도 의정부시 의정부동 푸르미텔 20x호..


이런식으로 깔끔하게 예제가 수행된다. 위에 null이란 것은 String 필드에 아무것도

데이터가 들어있지않음을 표시하는 것이다. 위 예제에서 첫번째 생성자는 전화번호와

주소를 넘기지 않았기 때문에 출력할 데이터가 없어서 null이 들어온 것이다.

참고로 int 형에는 0 , 불리언 타입에는 false, 그 밖의 타입은 null로 데이터없음을

표현한다.

생성자의 구분 방법 

앞서 설명 했듯 생성자는 파라미터 변수의 수, 타입, 순서로 구분된다. 

하지만 파라미터 변수의 이름은 구분의 기준이 되지 않는다. 그렇기 때문에 다음 두 생성자는

잘못 된것이다.

SubscriberInfo(String name, String id, String password){
this.name = name;
this.id = id;
this.password = password;
}
SubscriberInfo(String name, String id, String address){
this.name = name;
this.id = id;
this.address = address;
}

두 생성자가 있다. 하나는 이름, 아이디, 비밀번호를 다른하나는 이름, 아이디, 주소를 

파라미터로 넘겨주고 있다. 이렇게 보면 두 생성자는 다른 것이라고 우린 알 수 있지만

컴퓨터가 구분 할 수는 없다. 우선 앞서 말했듯 생성자이름은 구분의 기준이 되지않고

파라미터로 넘어가는 데이터 또한 두 생성자 모두 전부 String 형에 파라미터 수도 같기 

때문이다. 이런식으로 생성자 선언을 하면 오류가난다. 잘못된 방법이다.

디폴트 생성자

앞에서 생성자를 선언해서 파라미터를 넘겨주는 방법을 배웠다. 하지만 생성자는 잘만들어놓고

정작 파라미터없이 실행을 하면 어떻게 될까? 답은 컴파일 오류이다. 그렇기 때문에 값이 없을 때를

대비하여 만들어 놓는 생성자가 디폴트 생성자 일명 , no-arg constructor 이다. 

이 놈을 추가해 주면 파라미터 없이 수행을 해도 컴파일 오류가 나지 않는다.

SubscriberInfo(){
}
SubscriberInfo(String name, String id, String password){
this.name = name;
this.id = id;
this.password = password;
}
이런 식이다. 생성자를 하나더 만드는데 안에 받는 파라미터 없이 빈 괄호만 써준다. 넘어오는 것이

없으니 안에서 수행 할 것도 없다. 그냥 중괄호도 닫아준다. 그러고 실행을 하면 

이름 : null
아이디 : null
비밀번호 : null
전화번호 : null
주소 : null

오류 없이 데이터가 없다 라고 뿌려준다. 

전에 포스팅 했던 16 번 객체와 클래스 편을 봤다면 거기나온 GoodsStock 클래스는 생성자가

없었는데 파라미터없이 객체를 생성해도 컴파일 오류가 안났었다. 그 이유는 GoodsStock 에는

생성자가 아예 하나도 없었기 때문이다. 그럼 자바 컴파일러는 위에 방금 만들어본

디폴트 생성자를 하나 추가해서 오류없이 돌려준다. 하는 일은 없다 다만 오류를 안나게 하는거?

근데 위  SubscriberInfo는 생성자가 두개나 있었기에 자동으로 디폴트 생성자가 만들어지지 

않았던 것이다.

생성자에서 생성자 호출하기 

앞에서 보는듯 생성자가 하는일은 비슷비슷하다. 이럴때 똑같은 생성자 호출문을 두번씩 

쓰기보다 생성자에서 생성자를 호출하는 방법을 사용하는 것이 더 좋다. 

this(name,id,password);

이렇게 생성자 안에서 다른 생성자를 호출하면 같은 클래스에 있는 생성자 중에서 파라미터의

수, 타입, 순서가 맞는 생성자가 호출된다. 

SubscriberInfo(String name, String id, String password){
this.name = name;
this.id = id;
this.password = password;
}
SubscriberInfo(String name, String id, String password, 
String phoneNo, String address){
this(name, id, password);
this.phoneNo = phoneNo;
this.address = address;
}

이렇게 두번째 생성자가 첫번째 생성자를 호출하여 그 안의 데이터를 쓴다. 한가지 주의할 점은

저 구문은 반드시 생성자의 첫번째 명령문이어야 한다. 맨 위에 있어야 한다는 것이다.

저게 두번째 줄만 되도 오류가 나버린다. 

생성자편을 하면서 배우는 것이 많았다. 생성자.. 맨날 초기값을 셋팅해주는 놈으로 개념만 대충

알고 써먹지를 못하는 놈이었는데 이번기회로 .. 솔직히 지금도 내 프로젝트에 어떻게 써야할지 

좀 생각해봐야겠지만 아무튼. 생성자도 자주 접해서 익혀야 된다 . 그리고 아까 그 단순한 

출력 부분을 메소드화로 전체적인 코드가 깔끔해지는거.. 이런거 배우고 싶다 . 나같으면 아마

obj1.name , obj2.name 이러고 일일히 1,2, 안에 모든 파라미터를 한줄한줄 출력했을 것이다..

재밌다 그래도 




  출판사 : 한빛미디어 , 저자 : 김윤명 님의 뇌를 자극하는 Java프로그래밍에서 공부한 내용입니다.

'JAVA' 카테고리의 다른 글

JAVA] 18. 필드  (0) 2011.06.14
자바에서의 인스턴스란?  (1) 2011.06.13
JAVA] 16. 객체와 클래스  (0) 2011.06.09
JAVA] 15. 자바의 연산자 -2  (0) 2011.06.09
JAVA] 14. 자바의 연산자 -1  (0) 2011.06.08
posted by 젊은쎄오
: