Media Log


1. 생성자


전 강좌에서 오토바이 예제를 보셨었죠? 그 예제에서 오토바이 한대를 더 추가시켜보도록 할까요? 


class Vehicle {

    private int speed = 0; // 현재 속도를 나타내는 필드

    private int maxSpeed = 100; // 최대 속도를 나타내는 필드


    public int showSpeed() // 현재 속도를 보여준다

    {

        return speed;

    }


    public int showMaxSpeed() // 최대 속도를 보여준다

    {

        return maxSpeed;

    }


    public void speedUp(int increment) // 속도를 낸다

    {

        if(speed + increment > maxSpeed){

            System.out.println("최대 속도 " + maxSpeed + "km/h를 넘어설 수 없습니다.");

        }else{

            speed += increment;

        }

    }


    public void speedDown(int decrement) // 속도를 줄인다

    {

        if(speed - decrement < 0){

            System.out.println("속도는 0 아래로 떨어질 수 없습니다.");

        }else{

            speed -= decrement;

        }

    }

}


class VehicleMain {

    public static void main(String[] args) {

        Vehicle bike1 = new Vehicle();

        Vehicle bike2 = new Vehicle();


        bike1.speedUp(10);

        System.out.println("bike1의 속도: " + bike1.showSpeed() + "km/h, bike1의 최대속도: " + bike1.showMaxSpeed());

        bike2.speedUp(20);

        System.out.println("bike2의 속도: " + bike2.showSpeed() + "km/h, bike2의 최대속도: " + bike2.showMaxSpeed());

    }

}


결과:

bike1의 속도: 10km/h, bike1의 최대속도: 100

bike2의 속도: 20km/h, bike2의 최대속도: 100


우리가 예상하는 대로 값이 출력되었죠? 그런데 생각해보면 실세계에서의 오토바이는 기종에 따라 최대 속도가 서로 다를 수가 있습니다. 즉, bike1과 bike2의 최대 속도는 같거나 다를수도 있다는 말이 됩니다. 만약에, bike1과 bike2의 최대 속도가 서로 다르다고 가정하고 위의 예제를 수정해봅시다. 우리가 지금까지 배운 바로는 객체 생성시 값을 같이 넘겨주어 초기화 하는 방법을 모릅니다. 어쩔수 없이 Vehicle 클래스 내에 초기화 메소드를 하나 정의하여 사용하여야 합니다. InitMember라는 메소드를 정의하고 이 메소드를 사용해서 최대 속도를 초기화 시킨다고 합시다. 그런데 이 방법은 객체를 생성하고 값을 초기화 시키는 문장이 두줄씩이나 차지하고 최대 속도를 초기화 시킨 후에도 maxSpeed의 값 변경이 가능합니다. 이게 왜 문제가 될까요? 당연히 오토바이의 최대속도는 고정된 값이여야 합니다. 하지만 InitMember 메소드를 정의하여 멤버 변수를 초기화 시키는 방법을 택했는데 개발자가 혹시 모르게 InitMember 메소드를 다시한번 호출한다면 어떻게 될까요? 

Q: 그리고 두줄씩이나 차지하고 있는게 왜 문제가 될까요?
자바는 객체를 빈번히 사용합니다. 만약 수십개의 Vehicle 객체를 생성한다고 가정하고 그 객체마다 가지는 maxSpeed를 수정해야 한다고 생각해봅시다. 보기 좋지 않을뿐만 아니라 불필요하게 공간을 많이 차지합니다.

Q: 그렇다면 어떤 방법을 택해야 될까요?
여기서 우리가 이번에 배울 생성자(Constructor)를 사용하면 위의 두문제를 쉽게 해결할 수 있습니다.

생성자를 바로 사용해봅시다. 생성자를 사용하여 위의 예제를 조금 수정했습니다.

class Vehicle {
    private int speed = 0; // 현재 속도를 나타내는 필드
    private int maxSpeed; // 최대 속도를 나타내는 필드

    public Vehicle(int mspeed) // 생성자!
    {
    System.out.println("생성자가 호출되었습니다.");
        maxSpeed = mspeed;
    }

    public int showSpeed() // 현재 속도를 보여준다
    {
        return speed;
    }

    public int showMaxSpeed() // 최대 속도를 보여준다
    {
        return maxSpeed;
    }

    public void speedUp(int increment) // 속도를 낸다
    {
        if(speed + increment > maxSpeed){
            System.out.println("최대 속도 " + maxSpeed + "km/h를 넘어설 수 없습니다.");
        }else{
            speed += increment;
        }
    }

    public void speedDown(int decrement) // 속도를 줄인다
    {
        if(speed - decrement < 0){
            System.out.println("속도는 0 아래로 떨어질 수 없습니다.");
        }else{
            speed -= decrement;
        }
    }
}

class VehicleMain {
    public static void main(String[] args) {
        Vehicle bike1 = new Vehicle(110);
Vehicle bike2 = new Vehicle(140);

        bike1.speedUp(90);
        System.out.println("bike1의 속도: " + bike1.showSpeed() + "km/h, bike1의 최대속도: " + bike1.showMaxSpeed() + "km/h");
        bike2.speedUp(120);
        System.out.println("bike2의 속도: " + bike2.showSpeed() + "km/h, bike2의 최대속도: " + bike2.showMaxSpeed() + "km/h");
    }
}

결과:
생성자가 호출되었습니다.
생성자가 호출되었습니다.
bike1의 속도: 90km/h, bike1의 최대속도: 110
bike2의 속도: 120km/h, bike2의 최대속도: 140

아까의 예제와 달라진 부분을 찾아봅시다. 먼저 5행을 보시면 생성자가 등장했습니다. 여기서 알수있는 생성자의 특징은, 클래스와 동일한 이름을 갖는 메소드이며 생성자는 어떠한 값도 반환(return)하지 않습니다. 또한 반환형을 지정하지도 않습니다. 위 예제에 나타나지 않았지만 생성자는 오버로딩(여러번 생성자를 등장시킬 수 있음)이 가능합니다.

이제 쭉쭉 내려가서 42~43행을 봅시다.
        Vehicle bike1 = new Vehicle(110);
Vehicle bike2 = new Vehicle(140);

달라진 점이 뭔고 하니, 클래스명 옆의 괄호안에 인자(110, 140)가 붙었죠? 다시 생성자를 보시면 매개변수를 넘겨 받을수 있는 공간이 있습니다. 값이 넘어오면 그 값을 그대로 maxSpeed에 넣는 역할을 합니다. 결과를 살펴보시면, "생성자가 호출되었습니다."라는 문자열이 출력됬습니다.(7행에서 생성자 호출시 출력) 즉 객체를 생성하고 동시에 생성자가 딱 한번만 호출됩니다.

그리고 생성자는, 우리가 따로 생성자를 작성하지 않고 인자를 넘겨주지 않아도 호출됩니다. 이 경우에는 디폴트 생성자(Default Constructor)가 호출됩니다. 우리가 따로 생성자를 정의하지 않아도 JVM(자바 가상 머신, Java Virtual Machine)이 디폴트 생성자를 제공해주기 때문이죠. 디폴트 생성자는 인자가 없으며, 내용이 비어있으므로 하는일이 아무것도 없습니다. 그렇기 때문에 전 강좌에서 생성자를 작성하지 않아도, 에러가 뜨지 않았던거죠.

다시 돌아가서, 결과를 보면..
bike1의 속도: 90km/h, bike1의 최대속도: 110
bike2의 속도: 120km/h, bike2의 최대속도: 140

최대속도는 우리가 지정한 대로 각각 100, 140이 나온것을 확인하실 수 있습니다. 

오늘은 생성자에 대해 알아보았습니다. 여기 까지 읽느라 수고 많으셨고, 궁금하신 부분은 댓글을 달아주시면 참고하여 부가 설명을 달도록 하겠습니다.

  1. 김승현 at 2012.10.06 19:58 신고 [edit/del]

    감사합니다~

    Reply
  2. 수강생 at 2013.01.14 22:44 신고 [edit/del]

    좋은 강의 감사드립니다^^

    Reply
  3. 이거질문 at 2013.02.22 18:25 신고 [edit/del]

    public class balls{
    private int b1;
    private int b2;
    private int b3;
    private int b4;
    private int b5;
    private int a=1;
    public balls(int c1,int c2,int c3,int c4,int c5){
    b1=c1;
    b2=c2;
    b3=c3;
    b4=c4;
    b5=c5;
    }
    public void isitbigger(int f,int s){
    if(f>s)System.out.println("#test "+a+": First one is bigger.");
    if(f<s)System.out.println("#test "+a+": First one is smaller.");
    if(f==s)System.out.println("#test "+a+": First one is as big as second one.");
    a++;
    }
    }

    public class learnclassmain {
    public static void main(String[] args) {
    balls system1 = new balls(5,4,3,2,1);

    system1.isitbigger(b1,b2);
    system1.isitbigger(b2,b3);
    system1.isitbigger(b4,b1);
    system1.isitbigger(b5,b3);
    }
    }
    이게 안돼네요 고쳐주세요ㅠㅠ

    Reply
    • BlogIcon EXYNOA at 2013.02.22 21:50 신고 [edit/del]

      b1, b2 역시도 balls 클래스의 멤버이기 때문에 system1.b1 이런식으로 접근을 하셔야 합니다. 그리고 balls 클래스 내의 멤버 변수는 모두 public으로 두셔야 할것 같습니다.

  4. park at 2013.05.02 17:45 신고 [edit/del]

    생성자를 호출하였습니다에서 consol에서 왜 생성자를 호출하였습니다가 2번나온건가요?

    Reply
  5. 고마워요 at 2013.07.12 14:20 신고 [edit/del]

    자바를 공부했었다가 대부분 잊고 다시 공부하는데 쏙쏙 들어오는것 같습니다. 고맙습니다.

    Reply
  6. lee at 2014.03.13 16:58 신고 [edit/del]

    항상감사합니다

    Reply
  7. 감사드립니다 at 2016.06.30 11:16 신고 [edit/del]

    ^^좋은자료감사드립니다\

    Reply
  8. at 2016.11.25 17:36 신고 [edit/del]

    정말 감사합니다.
    대학 때 강의시간에 강의로 듣던 것 보다 이해가 훨신 잘됩니다.
    좀 더 쭉쭉 해보도록 하겠습니다^^

    Reply
  9. CY at 2017.02.01 21:11 신고 [edit/del]

    좋은 자료 감사합니다~
    질문이 하나 있습니다.

    Vehicle bike1 = new Vehicle(150);
    Vehicle bike2 = new Vehicle(100);

    bike1.SpeedUp(140);
    System.out.println("오토바이의 속도는 " + bike1.ShowSpeed() + "km/h입니다.");
    bike2.SpeedUp(140);
    System.out.println("오토바이의 속도는 " + bike2.ShowSpeed() + "km/h입니다.");

    이런 코드에서는 결과가
    오토바이의 속도는 140km/h입니다.
    최대 속도가 100km/h를 넘어설 수 없습니다.
    오토바이의 속도는 0km/h입니다.
    요렇게 나올 건데...

    만약 오토바이 속도가 0km 아래로 떨어지거나 최대 속도를 넘길 때
    원래 명령에서 나오는 방법이 있을까요?

    아얘 함수에서 나오게 되면 그 다음에 만약 다른 명령문이 있을 때는 그것까지 사라져 버리니깐
    그것도 안 되고 그냥 딱 위의 코드를 컴파일 했을 때

    오토바이의 속도는 140km/h입니다.
    최대 속도가 100km/h를 넘어설 수 없습니다.

    만 나올 수 있게 어떻게 할까요?

    답변 부탁드립니다~

    Reply

submit

티스토리 툴바