본문 바로가기

JAVA

생성자를 메서드라고 할 수 있을까?

생성자(Constructor)

1. 객체의 초기화를 담당한다.
2. 클래스의 이름과 동일한 이름을 가진다.
3. 반환 타입을 정의하지 않으며, 객체를 생성할 때 자동으로 호출된다.
4. 객체 생성 시 필요한 초기 설정을 수행하거나, 초기 값을 할당하는 데 사용된다(가지고 있는 멤버들을 메모리에 올려 객체를 생성하는 역할).

 

 

메서드(Method)

1. 객체가 수행할 수 있는 동작이나 행위를 정의한다.
2. 사용자가 정의한 이름을 가지며, 특정 작업을 수행한다.
3. 반환 타입을 명시적으로 정의해야 하며, 객체 또는 클래스에 따라 호출된다.
4. 객체의 상태를 변경하거나, 값을 계산하여 반환하는 등의 작업을 수행한다.

 

public class Person {
    String name;
    int age;

    // 생성자(Constructor)
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // 메서드(Method)
    public void introduce() {
        System.out.println("Hello, my name is " + name + " and I am " + age + " years old.");
    }
    
    public static void main(String[] args) {
        // Person 객체 생성 및 메서드 호출
        Person person = new Person("John", 30);
        person.introduce(); // "Hello, my name is John and I am 30 years old." 출력
    }
}

 

 

유사성

1. 구문(Syntax) : 생성자와 메서드 둘 다 클래스 내에서 정의되며, 매개변수를 가질 수 있다.
2. 오버로딩(Overloading) 가능 : 둘 다 오버로딩이 가능하다. 즉, 같은 이름으로 여러 생성자나 메서드를 정의할 수 있지만 매개변수의 타입이나 개수가 달라야 한다.

 

차이점

1. 목적과 사용 시점 :

생성자 : 객체 생성 시 초기화를 위해 사용된다. 객체의 생명주기가 시작될 때 딱 한 번, 자동으로 호출된다. 생성자는 객체가 정상적으로 작동하기 위한 초기 상태를 설정하는 데 중점을 둔다.
메서드: 객체가 이미 생성된 후에 호출된다. 객체의 행동을 정의하며, 객체의 생명주기 동안 여러 번 호출될 수 있다. 메서드는 객체가 수행할 수 있는 작업을 정의하고, 필요에 따라 값을 반환할 수 있다.

 

2. 반환 타입 :

생성자 : 반환 타입을 가지지 않으며, 클래스의 이름과 동일하다. 실제로 생성자는 객체 자신(this)을 반환하는 것이 아니라, 새로 생성된 객체를 초기화하는 역할을 한다.
메서드 : 반환 타입이 있어야 하며(반환하지 않는 메소드의 경우 void 사용), 어떤 타입의 값을 반환할 수도 있다. 메서드 이름은 생성자와 달리 클래스 이름과 동일할 필요가 없다.

 

3. 상속,  오버라이딩(Overriding) :

생성자 : 상속되지 않는다. 자식 클래스는 부모 클래스의 생성자를 상속받지 않으며, 필요한 경우 super 키워드를 사용하여 부모 클래스의 생성자를 명시적으로 호출할 수 있다.
메서드 : 상속될 수 있다. 자식 클래스에서는 부모 클래스로부터 상속받은 메서드를 오버라이드(재정의)할 수 있다.

 

4. 명시적 호출:

생성자 : 객체를 생성하는 new 연산자와 함께 자동으로 호출된다. 직접 호출할 수 없다(단, 같은 클래스의 다른 생성자 호출 시 this 키워드 사용 가능).
메서드 : 객체가 생성된 후, 객체나 클래스 이름을 통해 언제든지 명시적으로 호출할 수 있다.

 

 

아래는 오버로딩과 오버라이딩의 예시이다.

 

생성자 오버로딩

public class Person {
    String name;
    int age;

    // 이름과 나이를 매개변수로 받는 생성자
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // 이름만 매개변수로 받는 생성자
    public Person(String name) {
        this.name = name;
        this.age = 0; // 나이는 기본값으로 설정
    }
}

 

메서드 오버로딩

public class Calculator {
    // 정수 덧셈 메서드
    public int add(int a, int b) {
        return a + b;
    }

    // 실수 덧셈 메서드
    public double add(double a, double b) {
        return a + b;
    }
    
    public static void main(String[] args) {
        Calculator calc = new Calculator();
        
        System.out.println(calc.add(5, 3)); // 정수 덧셈
        System.out.println(calc.add(5.5, 3.2)); // 실수 덧셈
    }
}

 

생성자 호출 (오버라이딩 X)

class Parent {
    Parent() {
        System.out.println("Parent Constructor");
    }
}

class Child extends Parent {
    Child() {
        super(); // Parent 클래스의 생성자 호출
        System.out.println("Child Constructor");
    }
}

 

메서드 오버라이딩

class Animal {
    public void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Dog barks");
    }
}

 

 

결론

누군가는 생성자를 특별한 메서드라고도 지칭하고 이 역시 맞는 말이라고 생각한다. 하지만 필자는 생성자와 메서드를 서로 다르다고 보는게 맞다고 생각한다. 구조상 약간의 유사성과 오버로딩이라는 유사성을 띄지만, 상대적으로 더 많은 차이점을 비롯해 각각의 목적과 역할이 분명히 구분되어 있기 때문이다.