Java - 메소드 더 알아보기

민찬홍·2023년 9월 13일

Java

목록 보기
19/31

🧩 메소드 오버로딩

  • 같은 메소드 이름, 다른 매개변수
  • 다른 자료형의 값들로 같은 성질의 작업을 정의할 때
	static int add(int a, int b) { return a + b; }

    //  매개변수의 개수가 다름
    static int add(int a, int b, int c) { return a + b + c; }

    //  매개변수의 자료형이 다름
    static double add(double a, double b) { return a + b; }

    //  매개변수의 자료형 순서가 다름
    static String add(String a, char b) { return a + b; }
    static String add(char a, String b) { return a + b; }

    //  ⚠️ 반환 자료형이 다른 것은 오버로딩 안 됨 - 다른 함수명 사용
    //  static double add(int a, int b) { return (double) (a + b); }

위에처럼 메소드의 이름이 같더라도 매개변수의 자료형이 다르거나 매개변수의 자료형 순서가 다르면 사용할 수 있다. 하지만 아래의 주석처리된 코드를 보면 위의 첫번째 메소드와 매개변수의 자료형, 매개변수의 개수 모두 같지만 반환형이 다르다. 이 경우에는 오버로딩이 되지 않는 것을 볼 수 있다.

아래는 위의 메소드를 사용하는 예시이다.

		int res1 = add(1, 2); // 🔴 스텝인투로 들어가 볼 것
        int res2 = add(3, 4, 5);
        double res3 = add(1.2, 3.4);
        String res4 = add("로보트 태권", 'V');
        String res5 = add('X', "Men");

자바는 자료형을 엄격하게 따지기 때문에 메소드의 매개변수에 따라 그에 맞는 메소드가 호출된다.


🧩 원시형 매개변수 vs 참조형 매개변수

public class Ex02{
	public static void main(String[] args){
    
    	int intNum = 3; // intNum: 3
        modifyIntArg(intNum); // intNum:3

        int[] intNums = {1, 2, 3}; // intNums : [1,3,3]

		//  배열은 참조형이지만 그 안의 값들은 원시형
        modifyIntArg(intNums[0]);
        
        //  참조형인 배열 자체를 인자로 사용 // intNums:[1,3,3]
        modifyAryElem(intNums);
        
    }   // 🔴 
    
	//  ⭐️ 원시값은 '복사해서' 가져옴
    //  메소드 내부에서 값을 변경해도 원본에 영향 끼치지 않음
    static void modifyIntArg (int num) {
        System.out.printf("수정 전: %d%n", num++);
        System.out.printf("수정 후: %d%n", num);
    }

    //  ⭐️ 참조값은 주소값이므로 원본 그 자체를 가리킴
    static  void modifyAryElem (int[] ary) {
        System.out.printf("수정 전: %d%n", ary[1]++);
        System.out.printf("수정 후: %d%n", ary[1]);
    }
}    

위의 코드는 매우 중요하다. 원시자료형을 인자로 넘겨주게 되면 그 복사값이 메소드의 매개변수로 넘어가 원본에는 변화가 없다. 하지만 참조형인 배열 자체를 인자로 사용하면 주소가 복사가 되는 것이라서 원본에도 변화가 있다. 쉽게 말하면 집문서의 원본이나, 집문서의 복사본이나 같은 집을 가리키는 것은 똑같다. 따라서 주소의 복사본이 매개변수로 들어와 값을 변경하면 원본의 값도 변경되는 것이다.

결론적으로 참조값을 인자로 넘겨받은 메소드는 결국 원본에도 영향을 미친다

❗️ 메소드를 사용할 때 외부의 값을 직접 바꾸거나, 혹은 어떤 인자를 참조형으로 받아와서 그 안의 내용을 바꾸는 것은 위험하다. 이는 협업하는 사람이 메소드를 호출할 시 외부에 어떤 값이 바뀌는지 모르는 경우를 만들 수도 있다.

  • 🌟 참조형 변수를 인자를 사용할 때는 이 점을 꼭 유의하자!

🧩 재귀 메소드

  • 스스로를 호출하는 메소드
  • 호출시마다 메모리에 스택이 축적 - 초과시 stack overflow 에러
		static void upTo5 (int start) {
        System.out.println(start);
        if (start < 5) {
            upTo5(++start);
        } else {
            System.out.println("-- 종료 --");
        }
    }
		upTo5(0);
        upTo5(2);
        upTo5(4);

  • 다른 메소드를 호출한 메소드는 호출된 메소드가 종료될 때까지 메모리에 남아 있음
    • 호출이 반복될수록 위와 같이 메소드들이 쌓이게 됨
		static int factorial (int num) {
        return num == 0 ? 1 : num * factorial(--num);
    }
		int fact1 = factorial(1);
        int fact2 = factorial(2);
        int fact3 = factorial(3);
        int fact4 = factorial(4);
        int fact5 = factorial(5);

꼬리 재귀 최적화

  • 재귀 코드를 내부적으로 루프 형태로 바꿔서 스택이 쌓이지 않도록 함
  • ❗️ 자바에서는 현재 기본적으로 제공하지 않음
  • 따라서 재귀 작업은 자바에서는 가능하면 사용하지 않거나 사용한다 하더라도 반복횟수가 너무 많아지는 작업에는 사용하지 말 것!
profile
백엔드 개발자를 꿈꿉니다

0개의 댓글