본문 바로가기

[2016 - 2019] 학부 정리/Java

[자바복습] 6. 메소드

[메소드]

메소드의 장점 <1. 코드의 재활용성이 높다. 2. 입력과 출력>

 

[1] 코드의 재활용성

1. 메소드 정의와 호출(직접 만들고 실행)

 
public class MethodDemo1 {
	public static void numbering() {
		int i = 0;
		while (i < 10) {
			System.out.println(i);
			i++;
		}
	}

	public static void main(String[] args) {
		numbering();
	}
}

 

 
결과)
0
1
2
3
4
5
6
7
8
9

 

 

위의 예제는 numbering이라는 이름의 메소드를 정의하고 있다. 이 메소드는 main이라는 이름의 메소드 안에서 호출되고 있다. 위의 코드는 아래의 코드와 정확하게 동일한 의미를 갖는다.

 

 

핑크색으로 표시한 부분의 코드를 numbering이라는 이름의 메소드로 묶어서 외부로 분리한 것이다. 그리고 메소드 numbering의 로직이 필요할 때 numbering();이라고하면 메소드 numbering의 로직이 실행된다.

 

 

2. main 메소드

main 메소드는 규칙이다. 여러분이 만들고 싶은 프로그램이 있다면 여러분은 반드시 public static void main(String[] args)가 이끄는 중괄호 안에 실행되기를 기대하는 로직을 위치시켜야 한다.

 

 

3. 메소드가 없다면?

 예를 들어,  0부터 9까지를 5번 출력해야 한다면 우리는 복붙을 다섯번 해야 할 것이다.

 
public class MethodDemo2 {

	public static void main(String[] args) {
		int i = 0;
		while (i < 10) {
			System.out.println(i);
			i++;
		}

		i = 0;
		while (i < 10) {
			System.out.println(i);
			i++;
		}

		i = 0;
		while (i < 10) {
			System.out.println(i);
			i++;
		}

		i = 0;
		while (i < 10) {
			System.out.println(i);
			i++;
		}

		i = 0;
		while (i < 10) {
			System.out.println(i);
			i++;
		}
	}

}

 

규모가 이정도인 경우엔 어렵지 않게 복붙을 할 수 있겠지만, 100번, 1000번을 해야하는 경우에는 복붙을 하기 힘들것이다. 또한 중간에 내용을 수정하기도 어려울 것이다. 그러나 메소드를 사용한다면 이러한 문제들을 현저히 줄일 수 잇다. 결과는 같지만 로직은 단 한번만 등장한다. 이러한 것을 재활용성이라고 한다.

 
public class MethodDemo1 {

	public static void numbering() {
		int i = 0;
		while (i < 10) {
			System.out.println(i);
			i++;
		}
	}

	public static void main(String[] args) {
		numbering();
		numbering();
		numbering();
		numbering();
		numbering();
	}
}

 

즉, 자주사용하는 로직을 메소드로 만들어두면 호출하는 것을 통해서 간편하게 로직을 재활용할 수 있다.

 

 

[2] 입력과 출력

우리가 아는 쓸모있는 대부분의 프로그램이 사용자의 입력에 따라서 다른 결과를 출력한다. 메소드는 프로그램 안에서 동작하는 하나의 작은 프로그램이라고 할 수 있다. 위에서 살펴본 numbering이라는 메소드는 항상 똑같은 동작만을 반복한다. 이것도 재활용이라는 측면에서는 장점이 있지만, 입력 값에 따라서 출력 값을 달리 제공한다면 더욱 쓸모 있는 프로그램이 될 수 있을 것이다.

 

1. 매개변수와 인자

메소드의 입력 값은 매개변수(parameter)를 통해서 이루어진다. 위의 예제를 조금 개선해보자. 이전 예제는 0부터 9까지의 숫자를 화면에 출력했다. 만약 필요에 따라서 0부터 4까지 출력하고 싶거나 0부터 8까지 출력하고 싶다면 어떻게 해야 할까? 각각에 맞는 메소드를 새로 정의해야 할까? 그렇게 해도 되지만 더 좋은 방법이 있다. 입력 값에 따라서 다른 출력 값을 갖도록 메소드를 정의하면 된다. 즉, 입력을 고민할 때가 된 것이다.

 

public class MethodDemo2 {

	public static void numbering(int limit) {
		int i = 0;
		while (i < limit) {
			System.out.println(i);
			i++;
		}
	}

	public static void main(String[] args) {
		numbering(5);
	}
}
</text>

결과는 0부터 4까지 출력한다. 메소드를 호출할 때 괄호에 값을 주고 있는데 저 값을 다른 값으로 바꿔보자. 값에 따라서 다른 결과가 출력되고 있다. 입력을 통해서 메소드의 동작을 제어하고 있다. 아래 그림을 보자.

메소드 numbering의 괄호 안에 위치한 숫자 5는 이 메소드가 호출될 때 limit이라는 변수의 값이 된다. 이 값은 메소드 numbering의 중괄호 안에서만 사용할 수 있다.

 

여기서 limit이라는 변수는 메소드 numbering의 정의 부에 있는 로직들에게 5라는 값을 전달하고 있다. 호출에서 입력한 값을 로직으로 매개 한다는 의미에서 이러한 변수를 매개변수라고 부른다. 영어로는 parameter다. 그리고 메소드를 호출할 때 전달된 값인 5를 '인자' 영어로는 argument라고 한다. 관습적으로는 매개변수와 인자를 구분하지 않고 부르는 경우도 많다

 

2. 복수의 인자

만약 메소드로 여러개의 입력값을 전달하고 싶다면 어떻게 해야 할까? 다음 예제는 위의 예제를 개선해서 출력할 숫자의 시작 값과 마지막 값을 입력값으로 전달하는 예제다.

public class MethodDemo3 {

	public static void numbering(int init, int limit) {
		int i = init;
		while (i < limit) {
			System.out.println(i);
			i++;
		}
	}

	public static void main(String[] args) {
		numbering(1, 5);
	}

}

 결과는 1부터 4까지가 출력된다. 위와 같이 입력 값을 복수로 받고 싶다면 콤마 뒤에 매개변수를 정의해주면 된다. 또 이 메소스를 호출할 때는 매개변수의 순서대로 인자를 배치하면 된다.

 

3. return

좀 더 활용도가 높은 출력방법이 있다.

public class MethodDemo5 {
    public static String numbering(int init, int limit) {
        int i = init;
        // 만들어지는 숫자들을 output이라는 변수에 담기 위해서 변수에 빈 값을 주었다.
        String output = "";
        while (i < limit) {
            // 숫자를 화면에 출력하는 대신 변수 output에 담았다.
            output += i;
            i++;
        }
        // 중요!!! output에 담겨 있는 문자열을 메소드 외부로 반환하려면 아래와 같이 return 키워드 뒤에 반환하려는 값을
        // 배치하면 된다.
        return output;
    }
 
    public static void main(String[] args) {
        // 메소드 numbering이 리턴한 값이 변수 result에 담긴다.
        String result = numbering(1, 5);
        // 변수 result의 값을 화면에 출력한다.
        System.out.println(result);
    }
}

메소드 내에서 사용한 return은 return 뒤에 따라오는 값을 메소드의 결과로 반환한다. 동시에 메소드를 종료시킨다. 한가지 잊지 말아야 할 점은 return을 통해서 반환할 값의 데이터 형식을 메소드의 이름 옆에 명시해주어야 한다는 것이다.

 

public static String numbering(int init, int limit){

메소드가 리턴 할 값을 명시함으로서 numbering이라는 메소드는 반드시 문자열의 값을 리턴한다는 것을 보장할 수 있는 장점이 있다.

만약 반환 값이 없다면 아래와 같이 void를 적어준다.

public static void numbering(int init, int limit){

 

 

4. 굳이 return을 쓰는 이유?

결론적으로 말하면 부품으로서의 가치를 높이기 위해서라고 할 수 있다. 만약 여러분이 이 메소드가 출력한 값을 화면에 출력하는 것이 아니라 파일에 기록하고 싶다면 어떻게 해야 할까? 또는 이메일로 보내고 싶다면 어떻게 해야 할까? 3개의 메소드를 만들고 용도에 따라서 코드를 재작성하는 것도 좋은 방법이다. 하지만 더 좋은 방법은 숫자를 출력하고, 숫자를 파일에 기록하고, 숫자로 이메일을 보내는 작업으로부터 숫자를 계산하는 로직을 분리하는 것이다. numbering은 자신이 어떻게 사용될지 모른다. 누구든지 numbering이라는 메소드를 호출할 때 초기값과 마지막 값을 입력하면 numbering은 숫자를 문자열의 형태로 반환하면 되는 것이다.

 

import java.io.*; 

public class MethodDemo6 {
	public static String numbering(int init, int limit) {
		int i = init;
		String output = "";
		while (i < limit) {
			output += i;
			i++;
		}
		return output;
	}

	public static void main(String[] args) {
		String result = numbering(1, 5);
		System.out.println(result);
		try { 
				// 다음 행은 out.txt 라는 파일에 numbering이라는 메소드가 반환한 값을 저장합니다.
			BufferedWriter out = new BufferedWriter(new FileWriter("out.txt"));
			out.write(result);
			out.close();
		} catch (IOException e) {
		} 
	}
}

return의 특성에 대해서 조금 더 알아보자. return은 값을 반환하는 동작을 한다. 그런데 이것은 return에 대한 반쪽짜리 설명이다. return은 메소드를 중단시키는 역할도 한다.

 
public class ReturnDemo {
    public static int one() {
        return 1;
        return 2;
        return 3;
    }
 
    public static void main(String[] args) {
        System.out.println(one());
    }
}

위의 코드는 컴파일조차 되지 않는다. 왜냐하면, return 은 메소드를 종료시키는 역할을 하므로 return이 처음 등장한 이후의 구문은 실행되지 않기 때문이다.

 

 

5. 복수의 리턴

 메소드는 여러 개의 입력 값을 가질 수 있다. 그렇다면 여러개의 출력하고 싶다면? 자바는 문법적으로 그런 기능을 제공하지 않는다. 하나의 변수에 여러개의 값을 담아서 출력하면 된다.

public class ReturnDemo1 {
	public static String getMember1() {
		return "홍길동";
	}

	public static String getMember2() {
		return "김길동";
	}

	public static String getMember3() {
		return "최길동";
	}

	public static void main(String[] args) {
		System.out.println(getMember1());
		System.out.println(getMember2());
		System.out.println(getMember3());
	}
}
</text>
<P> </P>
<pre name="code" class="brush:java;">
결과)
홍길동
김길동
최길동
</text>

 

하나의 메소드는 하나의 값만을 반환할 수 있기 때문에 위와 같이 각각의 회원정보를 반환하는 메소드를 만들었다. 무언가 비정상적이지 않은가? 이번엔 배열을 이용한 아래의 코드를 보자. 맴버를 담고 있는 배열을 반환하고 있다. 간단하지 않은가? 메소드 getMembers가 리턴한 배열을 members 변수에 담았다. 이 변수를 이용해서 여러 개의 데이터를 처리 할 수 있게 된다.

public class ReturnDemo1 {
	 
    public static String[] getMembers() {
        String[] members = { "홍길동", "김길동", "최길동" };
        return members;
    }
 
    public static void main(String[] args) {
        String[] members = getMembers();
        
        System.out.println(members[0]);
        System.out.println(members[1]);
        System.out.println(members[2]);
    }
</text>