본문 바로가기
👨‍💻 프로그래밍/Java, Kotlin, Spring

자바 17 - 자바 매소드(Method), 오버로딩, Call-by-Value

by 개발자 진개미 2021. 5. 4.
반응형

매소드는 함수라고도 불리며, 데이터를 받아 특정한 작업을 수행하고 다시 데이터를 내보내는 대상이다.

 

- 매소드를 왜 써야 할까?

- 매소드 선언

- Call-by-Value

- 오버로딩(Overloading)

 


매소드를 왜 써야 할까?

매소드는 기본적으로 프로그램을 더 간편하게 하고, 반복되는 코드를 줄여준다.

 

코드가 반복되는 걸 줄여주는 건 상당히 중요한데, 예를 들어 어떤 기능을 구현했다고 했을 때, 똑같거나 비슷한 코드를 반복해서 사용하면 오류가 일어났을 때나 수정을 하고 싶을 때 코드를 쓴 모든 부분을 수정해야 하지만, 매소드를 사용하면 매소드만 수정하면 매소드가 사용된 모든 부분에서 코드가 자동으로 수정되기 때문에 버그를 고치기도 편하고, 수정하기도 편하고, 테스트하기도 편하고, 개발할 때도 편하고, 코드를 읽을 때도 편하다.

 

예를 들어, 두 사람은 나이, 키, 몸무게를 비교해서 더 큰 사람을 알려주는 프로그램을 작성한다고 해 보자. 여기서, 숫자를 비교한다는 핵심적인 부분이 3번이나 반복되고, 나이, 키, 몸무게를 비교하고 변수에 저장하는 부분도 반복된다. 만약에 매소드를 사용하지 않고 이 프로그램을 작성한다고 해 보면 아래와 같이 된다.

 

import java.util.Scanner;

public class Compare {
	public static void main(String[] args) {
    	Scanner stdin = new Scanner(System.in);
        
        System.out.print("첫 번째 사람의 나이를 입력해 주세요: ");
        int age1 = stdin.nextInt();
        System.out.print("두 번째 사람의 나이를 입력해 주세요: ");
        int age2 = stdin.nextInt();
        if(age1 > age2) {
        	System.out.println(age1 + " 이 더 큽니다.");
        } else if(age2 > age1) {
        	System.out.println(age2 + " 이 더 큽니다.");
       	} else {
        	System.out.println("둘은 같습니다.");
        }
        
        System.out.print("첫 번째 사람의 키를 입력해 주세요: ");
        int height1 = stdin.nextInt();
        System.out.print("두 번째 사람의 키를 입력해 주세요: ");
        int height2 = stdin.nextInt();
	        if(height1 > height2) {
        	System.out.println(height1 + " 이 더 큽니다.");
        } else if(height1 > height2) {
        	System.out.println(height2 + " 이 더 큽니다.");
       	} else {
        	System.out.println("둘은 같습니다.");
        }


        System.out.print("첫 번째 사람의 몸무게를 입력해 주세요: ");
        int weight1 = stdin.nextInt();
        System.out.print("두 번째 사람의 몸무게를 입력해 주세요: ");
        int weight2 = stdin.nextInt();
	        if(weight1 > weight2) {
        	System.out.println(age1 + " 이 더 무겁습니다.");
        } else if(wegith2 > wegith1) {
        	System.out.println(age2 + " 이 더 무겁습니다.");
       	} else {
        	System.out.println("둘은 같습니다.");
        }
	}
}

 

상당히 긴 프로그램이고, 딱 봐도 반복되는 부분이 많아 보인다. 똑같은 프로그램은 매소드를 사용해서 작성하면 아래와 같이 된다.

 

import java.util.Scanner;

public class Compare {
	public static void main(String[] args) {
		int age1 = getInput("나이");
		int age2 = getInput("나이");
		System.out.println(max(age1, age2) + " 가 더 큽니다.");
	
		int height1 = getInput("키");
		int height2 = getInput("키");
		System.out.println(max(height1, height2) + " 가 더 큽니다.");

		int weight1 = getInput("몸무게");
		int weight2 = getInput("몸무게");
		System.out.println(max(weight1, weight2) + " 가 더 큽니다.");
	}
    
    public static int max(int var1, int var2) {
    	if(var1 > var2) {
        	return var1;
        } else if(var2 > var1) {
        	return var2;
        } else{
        	return -1;
        }
    }
    
    public static int getInput(String message) {
    	Scanner stdin = new Scanner(System.in);
        System.out.print(message + " 를 입력해 주세요.");
        int input = stdin.nextInt();
        return input;
    }
}

 

딱 봐도 보기 편하고, 더 간결해졌다. 무엇보다 중요한 것은, 코드의 재사용을 줄여 앞으로 다른 숫자들을 더 물어본다 하더라도 쉽게 물어볼 수 있다는 것이다.


매소드 선언

자바에서는 모든 매소드는 클래스 안에 존재한다. 애초에 클래스 안에 있는 함수를 매소드 라 하는데, 자바에서는 클래스 밖에 함수가 있을 수 없으니 당연히 모든 함수는 클래스이다. 클래스가 뭔지는 제쳐두고, 매소드를 선언하기 위해선 우선 클래스를 선언해야 한다. 클래스는 class라는 키워드로 선언한다.

 

class ex {
}


클래스를 선언하면 클래스 안에 매소드를 선언할 수 있는데, 매소드 선언의 첫 단계는 매소드의 특성을 나열하는 것이다. 매소드의 특성은 4가지 종류가 있다.

 

1. 매소드가 모든 프로그램이 볼 수 있는지(public), 같은 클래스 안에서만 사용되는지(private)

2. 매소드를 클래스의 인스턴스를 만들어야 사용할 수 있는지(static)

3. 어떤 인풋을 받는지

4. 어떤 아웃풋(return)을 내보내는지

 

가 있다. 우선, 1번과 2번은 추후에 자세히 다룰 것이고, 우선은 우리는 public 하고 static 한 매소드만 다뤄보자. 아래는 두 숫자를 받아서 더 큰 숫자를 되돌려주는 매소드의 예시이다.

 

public static int max(int var1, int var2)

 

매소드의 특성은 먼저 매소드의 사용 범위를 알려주고, static 한 지 알려주고, 어떤 아웃풋을 내보내는지 알려주고, 이름을 선언하고, 어떤 인풋을 받는지 알려준다. 위의 매소드는 public 하고, static 하며, 이름은 max이고, int타입의 데이터를 아웃풋 하고, int타입의 두 변수를 받는다.

 

매소드는 반드시 아웃풋을 return 해야 한다. 즉, int타입의 데이터를 리턴한다고 명시하면, 반드시 int타입의 데이터를 return 해야 하고, 리턴할 데이터가 없을 경우는 void타입의 데이터를 사용해서 리턴하지 않는다고 명시해야 한다. 아래의 코드는 String을 프린트하는 매소드이다. 

 

public static void print(String var) {
	System.out.println(var);
}

 

프린트만 하고 끝나는 프로그램이므로, 당연히 아웃풋이 없다. 그렇기 때문에 void를 써서 아웃풋이 없다는 걸 명시해야 한다.

 


Call-by-Value와 Call-by-Reference

매소드에 값을 줄 때는, 그 값의 복사본을 줄 수도 있고, 그 값을 가리키는 포인터를 줄 수도 있다. 그 값의 복사본을 줄 경우 당연히 원래 있던 값에 변화는 없기 때문에 매소드를 이용할 때는 값을 복사본을 주는지, 포인터를 주는지를 구분해야 한다. 자바에서는 일반적으로 그 값을 복사본을 준다. 

 

public class Ex {
	public static void main(String[] args) {
    	int var = 1;
        add(var);
        System.out.println(var);
    }
    	
    public static void add(int var) {
    	var++;
    }

 

위 코드의 결과는 1이다. 매소드에서 1을 더했지만, 매소드에 넣은 값이 var 값 그 자체가 아니라, var의 복사본을 주었으므로 원래 값에는 변화가 없다.


오버로딩(Overloading)

오버 로딩은 쉽게 말해 같은 이름의 매소드가 여러 개 있는 것이다. 이름이 같다면 매소드를 어떻게 구분할까? 매소드는 말했다시피 값을 받고, 뭔가를 한 뒤, 값을 돌려준다. 그렇기 때문에 이름이 같아도 받는 값의 종류가 다르거나, 돌려주는 값의 종류가 다르면 구별할 수 있다.

 

public class Ex {
	public static void main(String[] args){
    	int a = 1;
        int b = 2;
        double c = 3.14;
        double d = 2.17;
        
        System.out.println(add(a, b));
        System.out.println(add(c, d));
    }
   	
    public static int add(int var1, int var2) {
    	return var1 + var2;
    }
    
    public static double add(double var1, double var2) {
    	return var1 + var2;
    }
}

 

위의 코드에서는 같은 이름의 매소드가 있었지만, 데이터의 타입이 달랐기 때문에 아무런 문제 없이 사용이 가능했다.

 

매소드 오버로딩은, 같은 기능을 수행하지만, 여러 개의 데이터 타입을 사용할 때 유용하다. 물론, 각각 다른 이름의 매소드를 사용할 수도 있지만, 그럼 쓸데없이 코드가 복잡해지기 때문에 가능하다면 매소드 오버로딩을 적극적으로 활용해야 한다.


 

반응형

댓글