본문 바로가기
Back-End/Java

자바 메서드 호출과 값 복사 그리고 오버로딩

by 두두리안 2024. 10. 29.
728x90

자바에서의 메서드 호출과 값 복사는 아주 중요한 개념입니다. 여기서 핵심은 "자바는 항상 변수의 값을 복사해서 대입한다"는 것입니다. 이 원칙을 이해하면 메서드 호출 시 어떤 값이 변하고, 어떤 값이 변하지 않는지 쉽게 알 수 있습니다. 예제를 통해 설명해 보겠습니다.

예제 1: 변수의 값 복사

다음 코드는 num1 값을 num2에 복사한 후, num2를 수정해도 num1은 영향을 받지 않는 예시입니다.

코드 예시:

public class MethodValueExample {
    public static void main(String[] args) {
        int num1 = 5;
        int num2 = num1;  // num1의 값(5)을 num2에 복사
        num2 = 10;        // num2 값을 10으로 변경

        System.out.println("num1=" + num1);  // 출력: num1=5
        System.out.println("num2=" + num2);  // 출력: num2=10
    }
}

실행 결과:

num1=5
num2=10

설명: num1의 값이 num2에 복사되었기 때문에 num2를 변경해도 num1은 영향을 받지 않습니다.

예제 2: 메서드 호출 시 값 복사

다음 코드는 메서드 호출 시 값을 복사해서 전달하는 방식입니다. 메서드 내에서 변수를 수정해도 원본 변수는 변하지 않습니다.

코드 예시:

public class MethodValueExample {
    public static void main(String[] args) {
        int num1 = 5;
        System.out.println("1. changeNumber 호출 전, num1: " + num1); // 출력: 1. changeNumber 호출 전, num1: 5
        changeNumber(num1);
        System.out.println("4. changeNumber 호출 후, num1: " + num1); // 출력: 4. changeNumber 호출 후, num1: 5
    }

    public static void changeNumber(int num2) {
        System.out.println("2. changeNumber 변경 전, num2: " + num2); // 출력: 2. changeNumber 변경 전, num2: 5
        num2 = num2 * 2;
        System.out.println("3. changeNumber 변경 후, num2: " + num2); // 출력: 3. changeNumber 변경 후, num2: 10
    }
}

실행 결과:

1. changeNumber 호출 전, num1: 5
2. changeNumber 변경 전, num2: 5
3. changeNumber 변경 후, num2: 10
4. changeNumber 호출 후, num1: 5

설명: changeNumber 메서드에 num1을 넘겨도 num1의 값이 num2에 복사되어 전달됩니다. 따라서 num2를 수정해도 num1은 변경되지 않습니다. 자바는 항상 값을 복사해서 전달하기 때문에, 메서드 내에서의 변수 수정이 원래 변수에 영향을 미치지 않습니다.

예제 3: 값을 반환하여 변수 변경하기

만약 메서드에서 값을 변경한 후 이를 호출한 곳에서도 반영하고 싶다면, 메서드에서 값을 반환하고 그 값을 대입하는 방식이 필요합니다.

코드 예시:

public class MethodValueExample {
    public static void main(String[] args) {
        int num1 = 5;
        System.out.println("changeNumber 호출 전, num1: " + num1); // 출력: changeNumber 호출 전, num1: 5
        num1 = changeNumber(num1); // 메서드 호출 결과를 num1에 대입
        System.out.println("changeNumber 호출 후, num1: " + num1); // 출력: changeNumber 호출 후, num1: 10
    }

    public static int changeNumber(int num2) {
        num2 = num2 * 2;
        return num2;  // 변경된 값을 반환
    }
}

실행 결과:

changeNumber 호출 전, num1: 5
changeNumber 호출 후, num1: 10

설명: 여기서는 changeNumber 메서드가 num2를 수정하고, 그 결과를 반환하여 main 메서드에서 num1에 다시 대입합니다. 이렇게 하면 num1의 값이 10으로 변경됩니다.

예제 4: 명시적 형변환 (Casting)

메서드 호출 시 인자의 자료형이 맞지 않으면 명시적 형변환을 사용해야 합니다.

코드 예시:

public class MethodCastingExample {
    public static void main(String[] args) {
        double number = 1.5;
        printNumber((int) number); // double을 int로 변환하여 메서드 호출
    }

    public static void printNumber(int n) {
        System.out.println("숫자: " + n);
    }
}

실행 결과:

숫자: 1

설명: printNumber 메서드는 int형을 받지만 number는 double형입니다. 따라서 (int) number로 명시적 형변환을 통해 1.5를 1로 변환하여 전달해야 합니다.

이처럼 자바는 항상 값을 복사하여 대입하며, 값 복사의 원칙을 활용하면 변수의 변경 범위를 예측하기 쉽습니다.

예제 5:메서드 오버로딩 예제

아래 예제는 printNumber라는 이름으로 여러 가지 유형의 int, double, 그리고 String 값을 출력하는 오버로딩 메서드를 정의합니다.

코드 예시:

public class MethodOverloadingExample {

    // 정수형 인자를 받는 메서드
    public static void printNumber(int number) {
        System.out.println("정수: " + number);
    }

    // 실수형 인자를 받는 메서드
    public static void printNumber(double number) {
        System.out.println("실수: " + number);
    }

    // 문자열 인자를 받는 메서드
    public static void printNumber(String text) {
        System.out.println("문자열: " + text);
    }

    public static void main(String[] args) {
        printNumber(10);        // 정수형 메서드 호출
        printNumber(5.5);       // 실수형 메서드 호출
        printNumber("Hello");   // 문자열 메서드 호출
    }
}

실행 결과:

정수: 10
실수: 5.5
문자열: Hello

설명: printNumber 메서드는 오버로딩되어 int, double, 그리고 String 타입의 매개변수를 각각 받을 수 있습니다. 메서드를 호출할 때 자바는 인자의 자료형에 맞는 메서드를 자동으로 선택하여 호출합니다.

메서드 오버로딩의 활용: 여러 개의 인자

오버로딩은 메서드의 인자 개수가 다를 때도 사용될 수 있습니다.

코드 예시:

public class MethodOverloadingExample {

    // 매개변수 1개인 메서드
    public static void displayInfo(String name) {
        System.out.println("이름: " + name);
    }

    // 매개변수 2개인 메서드
    public static void displayInfo(String name, int age) {
        System.out.println("이름: " + name + ", 나이: " + age);
    }

    // 매개변수 3개인 메서드
    public static void displayInfo(String name, int age, String city) {
        System.out.println("이름: " + name + ", 나이: " + age + ", 도시: " + city);
    }

    public static void main(String[] args) {
        displayInfo("Alice");                // 매개변수 1개 메서드 호출
        displayInfo("Bob", 25);              // 매개변수 2개 메서드 호출
        displayInfo("Charlie", 30, "Seoul"); // 매개변수 3개 메서드 호출
    }
}

실행 결과:

이름: Alice
이름: Bob, 나이: 25
이름: Charlie, 나이: 30, 도시: Seoul

설명: displayInfo 메서드는 매개변수의 개수에 따라 오버로딩되어 있습니다. 호출할 때 전달하는 매개변수의 개수에 따라 맞는 메서드가 자동으로 선택됩니다.

메서드 오버로딩의 유의점

리턴 타입만으로는 오버로딩이 불가능합니다. 매개변수의 타입이나 개수가 다를 때에만 오버로딩할 수 있습니다.

오버로딩된 메서드는 매개변수 타입과 개수를 기준으로 결정됩니다. 같은 이름의 메서드라도 매개변수 구성이 동일하다면, 다른 리턴 타입을 가졌더라도 오버로딩할 수 없습니다.

잘못된 예시:

public class MethodOverloadingExample {

    // 잘못된 오버로딩 (리턴 타입만 다름)
    public static int add(int a, int b) {
        return a + b;
    }

    public static double add(int a, int b) {  // 컴파일 오류 발생
        return a + b;
    }
}

위 예제에서는 add(int, int) 메서드의 리턴 타입만 다르고 매개변수는 동일하여 컴파일 오류가 발생합니다.

오버로딩의 활용성

오버로딩은 코드의 가독성과 유연성을 높여줍니다. 같은 이름의 메서드를 다양한 입력 방식으로 호출할 수 있어, 코드의 일관성을 유지하면서도 다양한 매개변수 조합을 사용할 수 있게 합니다.

728x90