[아이티센 부트캠프] (일반 메서드)

이언덕·2026년 3월 22일

아이티센 부트캠프

목록 보기
9/115
post-thumbnail

[일반 메서드]

이번 범위는 객체지향으로 본격적으로 들어가기 전에,
일반 메서드를 직접 만들고 호출하는 기본을 먼저 익히는 단계다.

지금은 클래스 메서드, 인스턴스 메서드를 정확히 나누는 것이 중심이 아니다.
이번에는 먼저 일반 메서드가 왜 필요한지, 어떻게 만들고 호출하는지, 값을 어떻게 받고 돌려주는지를 이해하는 것이 핵심이다.

즉, 이번 정리는 객체지향으로 들어가기 전에 알아야 하는
메서드의 가장 기본 형태를 정리한 내용이라고 보면 된다.




1. 일반 메서드란 무엇인가

개념

일반 메서드는 이름을 붙여 놓은 코드 블록이다.
자주 쓰는 코드를 한곳에 묶어 두고, 필요할 때마다 이름으로 불러서 다시 사용할 수 있게 만든다.

예를 들어 같은 출력문을 여러 번 써야 한다면, 그 코드를 매번 복사해서 적는 대신 메서드 하나로 묶어 두는 편이 훨씬 깔끔하다.
그래서 메서드는 코드 중복을 줄이고, 프로그램 흐름을 보기 쉽게 만드는 역할을 한다.



함수와 메서드의 차이

간단하게 보면 함수는 독립적으로 호출하는 코드 단위이고,
메서드는 객체나 클래스에 속해 있는 코드 단위라고 이해하면 된다.

아주 단순하게 말하면 아래처럼 볼 수 있다.

  • 함수는 그냥 호출 가능
  • 메서드는 객체를 통해서 호출

다만 지금 배우는 자바 예제는 대부분 static 메서드라서 객체 없이도 바로 호출하고 있다.
그래서 이번 단계에서는 자바에서는 이런 코드 묶음을 우선 메서드라고 부른다 정도로 이해하면 충분하다.



왜 필요한가

메서드를 배우는 이유는 단순히 문법 하나를 더 외우기 위해서가 아니다.

같은 코드를 여러 번 써야 할 때 메서드로 묶어 두면 다시 쓰기 쉽고,
프로그램을 읽을 때도 “여기서는 이 기능을 호출하는구나” 하고 흐름을 더 빨리 파악할 수 있다.

즉, 메서드는 코드를 줄이는 도구이기도 하지만,
더 중요한 것은 코드를 정리하는 도구라는 점이다.




2. 일반 메서드를 볼 때 먼저 알아야 하는 것

자바에서는 메서드를 클래스 안에 만든다

자바에서는 코드를 아무 데나 작성하지 않는다.
메서드는 항상 클래스 안에서 만든다.

즉, 메서드는 혼자 떨어져 있는 것이 아니라
반드시 어떤 클래스 안에 들어 있는 형태로 작성된다.



프로그램은 main 메서드부터 시작한다

자바 프로그램을 실행하면 가장 먼저 main 메서드가 시작된다.
그래서 main은 프로그램의 시작점이라고 보면 된다.

즉, 지금까지 작성한 예제들도 전부
main 안에서 다른 메서드를 호출하는 방식으로 실행되고 있다.



메서드는 호출해야 실행된다

메서드는 만들어 두기만 한다고 자동으로 실행되지 않는다.
반드시 메서드명();처럼 호출문을 써야 안의 코드가 실행된다.

이 점을 먼저 알아야 뒤에서 나오는 예제들이 자연스럽게 이해된다.



제어자란 무엇인가

메서드 앞에는 필요에 따라 제어자가 붙을 수 있다.
제어자는 그 메서드를 어디서 사용할 수 있는지, 어떤 방식으로 호출할 수 있는지를 나타내는 말이다.

예를 들어 public, static 같은 것들이 제어자다.

public static void main(String[] args) {

위 코드에서

  • public → 다른 곳에서도 접근할 수 있게 하는 제어자
  • static → 객체를 만들지 않고도 사용할 수 있게 하는 제어자

라고 보면 된다.

제어자는 붙일 수도 있고 안 붙일 수도 있으며, 여러 개를 함께 붙일 수도 있다.
지금 단계에서는 public, static의 깊은 의미를 전부 외우기보다,
메서드 앞에는 이런 제어자가 붙을 수 있다 정도로 먼저 이해하면 충분하다.



메서드의 구성 요소

메서드는 보통 아래 요소들로 이루어진다.

제어자 반환형 메서드명(매개변수 선언) {
	실행할 코드
	return 반환값;
}

여기서 봐야 할 것은 다음과 같다.

  • 제어자 : 메서드를 어떻게 사용할지 정하는 부분
  • 반환형 : 메서드가 끝난 뒤 어떤 타입의 값을 돌려줄지
  • 메서드명 : 메서드의 이름
  • 매개변수 : 호출할 때 값을 받기 위한 변수
  • { } 안쪽 : 실제로 실행할 코드

또 메서드 이름 뒤에는 항상 ()가 붙는다.
괄호가 없으면 메서드 호출이 아니라 이름 자체만 가리키는 형태가 된다.

즉, 괄호가 있어야 “메서드를 사용한다”는 뜻이 분명해진다.
앞으로 메서드를 볼 때는
제어자 → 반환형 → 이름 → 괄호 → 실행 코드
이 순서로 보면 훨씬 읽기 쉽다.





메서드 사용하는 방법 문법

메서드는 호출하는 방식에 따라 여러 형태로 사용할 수 있다.

메서드명(아규먼트);

변수 = 메서드명(아규먼트);

메서드명(메서드명(아규먼트));

메서드명(아규먼트) + "입니다";

하나씩 보면 아래와 같다.

  • 메서드명(아규먼트);
    → 메서드를 그냥 실행만 하는 형태

  • 변수 = 메서드명(아규먼트);
    → 반환값이 있는 메서드의 결과를 변수에 저장하는 형태

  • 메서드명(메서드명(아규먼트));
    → 반환값이 있는 메서드를 다른 메서드의 인자로 넣는 형태

  • 메서드명(아규먼트) + "입니다";
    → 반환값을 문자열과 이어 붙이는 형태

즉, 반환값이 있는 메서드는 하나의 값처럼 다양하게 사용할 수 있다.
반대로 void 메서드는 값을 돌려주지 않기 때문에 이런 식으로 값처럼 사용할 수 없다.




3. 반환값이 없는 가장 기본 메서드

개념

메서드를 처음 배울 때는 가장 단순한 형태부터 보는 것이 좋다.

가장 기본적인 메서드는

  • 값을 받지 않고
  • 값을 돌려주지도 않고
  • 호출되면 정해진 일을 수행하는 메서드

이다.

이 형태를 먼저 이해해야 그다음에 매개변수, 반환값, 형변환 같은 내용이 자연스럽게 이어진다.

또 여기서 void는 값을 돌려주지 않는다는 뜻이다.
필요하면 return;을 사용해 실행을 끝낼 수도 있다.

즉, void 메서드에서의 return;은
값을 보내는 문장이 아니라 메서드 실행을 끝내는 문장으로 이해하면 된다.

예제: MethodTest1

package day4;

public class MethodTest1 {
	public static void main(String[] args) {
		System.out.println("main() 수행시작");
		printMyName();
		System.out.println(1);
		printMyName();
		System.out.println(2);
		printMyName();
		System.out.println(3);
		System.out.println("main() 수행종료");
	}

	static void printMyName() {
		System.out.println("유니코");
		return;
	}
}

// 출력결과
// main() 수행시작
// 유니코
// 1
// 유니코
// 2
// 유니코
// 3
// main() 수행종료

이 코드는 printMyName()이라는 메서드를 만들어 두고 여러 번 호출하는 예제다.
printMyName()은 괄호 안에 아무것도 없으므로 받는 값이 없다.
또 void이므로 돌려주는 값도 없다.

대신 호출되면 "유니코"를 출력하는 일을 수행한다.
즉, 이 예제는 메서드는 이렇게 만들고, 이렇게 부르면 실행되는구나를 가장 단순하게 보여준다.



핵심 포인트

이 코드에서 핵심은 두 가지다.

  • 첫째, printMyName()은 한 번 만들어 두면 여러 번 다시 쓸 수 있다.
  • 둘째, 메서드는 호출한 위치로 돌아온 뒤 그다음 문장을 계속 실행한다.

즉, 가장 기본적인 메서드는
값을 받지도 않고, 값을 돌려주지도 않지만, 호출되면 정해진 일을 수행하는 메서드다.



헷갈리기 쉬운 부분

메서드는 정의만 했다고 자동 실행되지 않는다.
printMyName();처럼 호출해야 실행된다.

또 main은 예외적으로 프로그램 시작 시 자동으로 실행되지만,
그 안에서 만든 다른 메서드들은 직접 호출해야 한다.




4. 반환값이 있는 메서드

개념

이번에는 실행만 하는 메서드가 아니라,
작업한 결과를 돌려주는 메서드를 본다.

이런 메서드는 void 대신 int, double, String 같은 반환형을 쓴다.
그리고 메서드 끝에서 return 값; 형태로 결과를 돌려준다.
반환값이 없으면 에러가 난다.

static String getMyName() {
	"유니코";                // 에러!!
}

즉, 반환값이 있는 메서드는
실행 + 결과 전달까지 함께 하는 메서드다.

예제: MethodTest1_1

package day4;

public class MethodTest1_1 {
	public static void main(String[] args) {
		System.out.println("[호출 예시1]");
		System.out.println(getMyName());

		System.out.println("[호출 예시2]");
		String name = getMyName();
		System.out.println(name);
		System.out.println(name);
	}

	static String getMyName() {
		return "유니코";
	}
}

// 출력결과
// [호출 예시1]
// 유니코
// [호출 예시2]
// 유니코
// 유니코

이 코드의 getMyName()은 "유니코"라는 문자열을 돌려주는 메서드다.
반환형이 String이므로, 메서드가 끝날 때 문자열 값을 돌려주고 있다.

이 예제에서는 그 반환값을 두 가지 방식으로 사용한다.

  • 첫째, System.out.println(getMyName());처럼 바로 출력한다.
  • 둘째, String name = getMyName();처럼 변수에 저장한 뒤 다시 사용한다.



핵심 포인트

반환값이 있는 메서드는 호출만 하고 끝나는 것이 아니라
결과 하나를 호출한 곳으로 넘겨준다는 점이 중요하다.

즉, void 메서드와 달리
반환값이 있는 메서드는 실행 결과를 꺼내서 다시 사용할 수 있다.



헷갈리기 쉬운 부분

반환값이 있는 메서드는 반드시 return 값;이 필요하다.
그냥 값만 써 놓는다고 반환되는 것이 아니다.

즉, 메서드 선언부에 String, int, double 같은 반환형을 적었다면
마지막에는 그에 맞는 값을 return으로 돌려줘야 한다.




5. 매개변수와 인자

개념

이제 메서드가 값을 받아서 동작하는 구조를 본다.
메서드를 선언할 때 괄호 안에 적는 변수는 매개변수(parameter)다.
그리고 메서드를 호출할 때 실제로 넘기는 값은 인자(argument)다.

즉, 매개변수는 받는 쪽 변수,
인자는 전달하는 쪽 실제 값이라고 이해하면 된다.

예제: MethodTest2

package day4;

public class MethodTest2 {
	public static void main(String[] args) {
		System.out.println("main() 수행시작");
		printMyName(5);
		System.out.println("main() 수행종료");
	}	

	static void printMyName(int num) {
		if (num <= 0)
			return;

		for(int i=1; i <= num; i++)
			System.out.println("유니코");
	}
}

// 출력결과
// main() 수행시작
// 유니코
// 유니코
// 유니코
// 유니코
// 유니코
// main() 수행종료

이 예제는 값을 하나 받아서 동작하는 메서드다.
printMyName(5)라고 호출하면 5가 num에 들어가고, 그 값만큼 반복해서 출력한다.

즉, 이 예제는
매개변수 하나를 받는 가장 기본적인 형태를 보여준다.

또 if (num <= 0) return;이 있기 때문에,
받은 값에 따라 메서드 실행이 중간에 끝날 수도 있다는 점도 함께 볼 수 있다.



예제: MethodTest3

package day4;

public class MethodTest3 {
	public static void main(String[] args) {
		System.out.println("main() 수행시작");
		printMyName(1, '#');
		System.out.println("--------------");
		printMyName(3, '*');
		System.out.println("--------------");
		printMyName(2, '@');
		System.out.println("--------------");
		printMyName((int)3.14, '%');
		System.out.println("main() 수행종료");
	}

	static void printMyName(int num, char deco) {
		for(int i=1; i <= num; i++)
			System.out.println(deco+"유니코"+deco);
	}
}

// 출력결과
// main() 수행시작
// #유니코#
// --------------
// *유니코*
// *유니코*
// *유니코*
// --------------
// @유니코@
// @유니코@
// --------------
// %유니코%
// %유니코%
// %유니코%
// main() 수행종료

이 메서드는 두 개의 값을 받는다.

  • int num
  • char deco

그리고 그 값을 이용해 몇 번 출력할지, 어떤 문자로 꾸밀지를 결정한다.
이 예제를 보면 같은 메서드라도
어떤 인자를 넘기느냐에 따라 결과가 달라진다는 점이 바로 보인다.



핵심 특징

매개변수와 인자를 사용할 때는 세 가지를 꼭 맞춰야 한다.

  • 개수
  • 순서
  • 타입
    예를 들어 (int, char) 형태로 받는 메서드라면
    호출할 때도 그 순서대로 맞춰서 넘겨야 한다.



형변환이 필요한 경우

이 예제의 마지막 줄은 아래와 같다.

printMyName((int)3.14, '%');

여기서 첫 번째 매개변수는 int이므로, 3.14를 그대로 넣을 수 없다.
그래서 (int)3.14처럼 형변환해서 넣고 있다.

즉,

  • printMyName(3, '%') → 가능
  • printMyName(3.14, '%') → 불가능
  • printMyName((int)3.14, '%') → 가능

이 흐름으로 이해하면 된다.



헷갈리기 쉬운 부분

매개변수와 인자는 이름이 비슷해서 자주 헷갈린다.

  • 매개변수 → 메서드가 받는 변수
  • 인자 → 호출할 때 넘기는 실제 값

이 둘을 구분해서 이해해야 뒤에서 나오는 예제들이 잘 보인다.




6. 매개변수와 반환값이 함께 있는 메서드

개념

앞에서는

  • 반환값 없는 메서드
  • 반환값 있는 메서드
  • 매개변수를 받는 메서드

를 따로 봤다.

이제는 이 둘이 합쳐진 형태를 본다.
즉, 값을 받아서 작업하고, 그 결과를 다시 돌려주는 메서드다.
이 형태가 실전에서 가장 자주 쓰이는 기본 구조다.

예제: MethodTest1_2

package day4;

public class MethodTest1_2 {
	public static void main(String[] args) {
		System.out.println(getSum(100, 200));
		int r1 = getSum(10, 20);
		System.out.println("결과값 : " + r1);
		
		System.out.println(getAvg(r1, 30));
		double r2 = getAvg(15, 20);
		System.out.println(r2);
		System.out.println((int)r2);
	}

	static int getSum(int num1, int num2) {  
		return num1+num2;
	}

	static double getAvg(double num1, double num2) {
		return (num1+num2)/2;
	}
}

// 출력결과
// 300
// 결과값 : 30
// 30.0
// 17.5
// 17

getSum은 int 두 개를 받아서 더한 결과를 int로 돌려준다.
getAvg는 double 두 개를 받아서 평균을 double로 돌려준다.

즉, 이 예제는
입력값을 받아 계산하고, 결과값을 반환하는 메서드를 가장 기본적으로 보여준다.



예제: MethodTest5

package day4;

public class MethodTest5 {
	public static void main(String[] args) {
		System.out.println("main() 수행시작");
		int result = operate(10,20);
		System.out.println("호출 결과1 : "+result);
		System.out.println("호출 결과2 : "+operate(100,200));
		int result2 = operate(11,22) % 2;
		if(result2 == 0)
			System.out.println("호출 결과3 짝수");
		else
			System.out.println("호출 결과3 홀수");
		System.out.println("호출 결과4 : "+operate(100,200,300));
		System.out.println(getName());
		System.out.println("*" + getName() + "*");
		System.out.println("main() 수행종료");		
	}	

	static int operate(int num1, int num2) {
		return num1+num2;
	}

	static int operate(int num1, int num2, int num3) {
		return num1+num2+num3;
	}

	static String getName() {
		return "김정현";
	}
}

// 출력결과
// main() 수행시작
// 호출 결과1 : 30
// 호출 결과2 : 300
// 호출 결과3 홀수
// 호출 결과4 : 600
// 김정현
// *김정현*
// main() 수행종료

이 예제는 매개변수와 반환값이 함께 있는 메서드를
실제로 어떻게 활용하는지 보여준다.

  • int result = operate(10,20); → 변수에 저장
  • System.out.println("호출 결과2 : "+operate(100,200)); → 바로 출력
  • operate(11,22) % 2 → 연산식에 사용
  • "*" + getName() + "*" → 문자열과 결합

즉, 값을 받아 계산한 뒤 돌려준 결과는
다시 여러 형태로 활용할 수 있다.



핵심 포인트

이 파트에서 중요한 것은 아래 흐름이다.
1. 값을 받는다.
2. 메서드 안에서 계산한다.
3. return으로 결과를 돌려준다.
4. 호출한 쪽에서 그 결과를 사용한다.

이 흐름이 이해되면 메서드의 기본 골격은 거의 잡힌 것이다.



메서드 안에서의 형변환

getAvg는 매개변수가 double이다.
그런데 호출할 때 int 값을 넣은 부분이 있다.

System.out.println(getAvg(r1, 30));
double r2 = getAvg(15, 20);

여기서는 int 값이 double로 바뀌어서 들어간다.
즉, 호출할 때 타입이 완전히 같지 않아도 자동 형변환이 가능한 경우에는 호출할 수 있다.



헷갈리기 쉬운 부분

반환형이 int면 int 결과를 돌려줘야 하고,
반환형이 double이면 double 결과를 돌려줘야 한다.

즉, return 뒤에 오는 값은
메서드 선언부의 반환형과 맞아야 한다는 점을 꼭 기억해야 한다.



7. 일반 메서드 활용

7-1. 같은 이름의 메서드 만들기 - 오버로딩

개념

오버로딩은 같은 이름의 메서드를 여러 개 만드는 것이다.
단, 아무렇게나 만들 수 있는 것은 아니고
매개변수의 개수나 타입이 달라야 한다.

즉, 자바는 메서드를 구분할 때
이름만 보는 것이 아니라 괄호 안의 매개변수 모양까지 함께 본다.

보기 1 그림은 매개변수의 타입이 같기 때문에 오버로딩 성립 ❌
보기 2 그림은 리턴타입이 달라서 어떤 메서드가 호출된 것인지 알 수가 없기 때문에 오버로딩 성립 ❌


두 메서드 모두 각각 다른 타입의 매개변수를 가지고 있기 때문에 오버로딩 성립 🅾️

예제: MethodTest4_1

package day4;

public class MethodTest4_1 {
	public static void main(String[] args) {
		System.out.println("main() 수행시작");
		printMyName(3, '*');
		printMyName("듀크", '$');
		printMyName("듀크", '$');
		printMyName("듀크", '$');
		printMyName("턱시", '!');
		System.out.println("main() 수행종료");
	}	

	static void printMyName(int num, char deco) {
		for(int i=1; i <= num; i++)
			System.out.println(deco+"유니코"+deco);
	}

	static void printMyName(String name, char deco) {
		System.out.println(deco+name+deco);
	}
}

// 출력결과
// main() 수행시작
// *유니코*
// *유니코*
// *유니코*
// $듀크$
// $듀크$
// $듀크$
// !턱시!
// main() 수행종료

이 예제에는 printMyName이라는 메서드가 두 개 있다.
이름은 같지만 매개변수 모양이 다르다.

그래서 자바는 호출할 때 넘긴 인자를 보고
어떤 메서드를 실행할지 구분할 수 있다.

헷갈리기 쉬운 부분

반환형만 다르고 매개변수가 같으면 오버로딩이 아니다.
오버로딩은 어디까지나 매개변수로 구분한다.



7-2. 배열을 매개변수로 전달하기

개념

메서드는 숫자 하나, 문자 하나만 받는 것이 아니다.
배열도 매개변수로 받을 수 있다.

배열을 넘기면 여러 값을 한꺼번에 처리하는 메서드를 만들 수 있어서
메서드 활용 범위가 훨씬 넓어진다.

예제: MethodTest6

package day5;

public class MethodTest6 {
	public static void main(String[] args) {
		System.out.println("main() 수행시작");
		System.out.println(add(10, 100));
		System.out.println(add(10, 20, 30));
		int nums[] = {10, 20, 30, 40};
        System.out.println("nums의 값 : "+nums);
		System.out.println(add(nums));
		System.out.println(add(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}));
		System.out.println(add(new int[5]));
		System.out.println("main() 수행종료");
	}

	static int add(int p1, int p2) {
		return p1+p2;
	}

	static int add(int p1, int p2, int p3) {
		return p1+p2+p3;
	}

	static int add(int[] p) {   
		System.out.println("p의 값 : "+p);
		int sum = 0;
		for(int i=0; i < p.length; i++)
			sum += p[i];
		return sum;
	}
}

// 출력결과
// main() 수행시작
// 110
// 60
// nums의 값 : [I@2b2fa4f7
// p의 값 : [I@2b2fa4f7
// 100
// p의 값 : [I@7ad041f3
// 55
// p의 값 : [I@251a69d7
// 0
// main() 수행종료

이 예제는 add를 여러 형태로 만든다.

  • 값 2개를 더하는 메서드
  • 값 3개를 더하는 메서드
  • 배열 전체를 더하는 메서드

즉, 같은 “더하기” 기능이더라도
받는 데이터 모양에 따라 메서드를 다르게 만들 수 있다.

헷갈리기 쉬운 부분

add(10, 20, 30, 40)처럼 4개를 바로 넘길 수는 없다.
그 형태로 받는 메서드가 없기 때문이다.

그래서 4개 이상을 넘기고 싶다면
지금처럼 배열에 담아서 보내는 방식을 사용할 수 있다.

배열을 매개변수로 넘기는 방식은 가장 기본적인 형태다.
가변 인자(...)는 이 방식을 더 편하게 사용할 수 있게 만든 문법이라고 보면 된다.



7-3. 가변 인자(...) 사용하기

개념

배열을 매개변수로 전달하면 여러 값을 한꺼번에 처리할 수 있다.
그런데 자바에서는 배열을 직접 만들어 넘기는 방식 외에도,
가변 인자(...)를 사용해서 값의 개수를 유동적으로 받을 수 있다.

가변 인자는 메서드 선언에서 아래처럼 쓴다.

int... p

이렇게 선언하면 호출할 때 값을 몇 개 넘길지 미리 정해 두지 않아도 된다.
즉, 2개, 3개, 5개, 0개처럼 개수가 달라도 한 메서드가 받을 수 있다.

결국 가변 인자는 여러 개의 값을 편하게 받기 위한 문법이고,
메서드 안에서는 배열처럼 사용할 수 있다.



핵심 특징

  • ...는 매개변수 선언에서만 사용할 수 있다.
  • 가변 인자는 항상 마지막 매개변수여야 한다.
  • 메서드 안에서는 배열처럼 length와 인덱스를 사용할 수 있다.
  • 자바 5부터 추가된 문법이다.

예제: MethodTest6_1

package day5;

public class MethodTest6_1 {
	public static void main(String[] args) {
		System.out.println("main() 수행시작");
		System.out.println(add(10, 100));
		System.out.println(add(10, 20, 30));
		System.out.println(add(new int[]{10, 20, 30, 40}));
		System.out.println(add(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}));
		System.out.println(add(new int[0]));
		System.out.println(add());
		System.out.println(add(10, 20, 30, 40, 50));
		System.out.println(add(11, 22, 33, 44, 55, 66, 77, 88, 99));
		System.out.println("main() 수행종료");
	}

	static int add(int p1, int p2) {
		return p1 + p2;
	}

	static int add(int p1, int p2, int p3) {
		return p1 + p2 + p3;
	}

	static int add(int... p) {
		int sum = 0;
		for(int i = 0; i < p.length; i++)
			sum += p[i];
		return sum;
	}
}

이렇게 가변 인자를 사용하면 호출할 때 배열을 직접 만들지 않고도 아래처럼 쓸 수 있다.

add();
add(10, 20, 30, 40, 50);
add(11, 22, 33, 44, 55, 66, 77, 88, 99);

즉, 배열을 직접 만들어 넘기지 않아도 여러 값을 바로 나열해서 전달할 수 있다는 점이 가변 인자의 가장 큰 장점이다.

MethodTest6은 배열로 여러 값을 받는 방식,
MethodTest6_1은 가변 인자로 더 편하게 받을 수 있다는 확장 설명으로 보면 된다.



헷갈리기 쉬운 부분

가변 인자는 리턴값을 배열로 받는 문법이 아니다.
어디까지나 매개변수를 가변적으로 받는 문법이다.

즉,

  • int... p → 여러 값을 매개변수로 받는 것
  • char[] getName(...) → 배열을 결과로 반환하는 것

이 둘은 서로 다른 개념이다.



7-4. 배열을 반환하기

개념

메서드는 배열을 받을 수도 있고,
반대로 배열 자체를 결과로 돌려줄 수도 있다.
즉, 결과값 하나만 반환하는 것이 아니라
여러 값을 담은 배열 전체를 반환할 수 있다는 뜻이다.

예제: MethodTest8

package day5;

public class MethodTest8 {
	public static void main(String[] args) {
		System.out.println("main() 수행시작");
		char[] returnValue = getName(true);
		System.out.println(returnValue);
		System.out.println(getName(!true));
		System.out.println("main() 수행종료");
	}

	static char[] getName(boolean type) {
		char ary[];
		if(type)
			ary =  new char[] {'J', 'A', 'V', 'A'};
		else 
			ary = new char[] {'P', 'Y', 'T', 'H', 'O', 'N'};
		return ary;
	}
}

// 출력결과
// main() 수행시작
// JAVA
// PYTHON
// main() 수행종료

이 메서드는 char[] 배열을 반환한다.
조건에 따라 JAVA 또는 PYTHON 글자를 담은 배열을 만들어 돌려준다.

여기서 중요한 점은 반환형이 char[]라는 것이다.
즉, 문자 하나가 아니라 문자 배열 전체를 결과로 넘기고 있다.

헷갈리기 쉬운 부분

char[]는 println()에서 문자처럼 보이지만,
모든 배열이 이런 식으로 출력되는 것은 아니다.

예를 들어 int[] 같은 배열은 보통
값 대신 배열의 참조 정보처럼 보인다.



7-5. 원본 배열을 바꾸는 경우와 새 배열을 만드는 경우

개념

배열을 다루는 메서드는 비슷해 보여도
동작 방식이 다를 수 있다.

  • 새 배열을 만들어서 반환하는 방식
  • 원본 배열 자체를 직접 바꾸는 방식

이 둘은 결과가 다르므로 구분해서 이해해야 한다.

예제: MethodTest9

package day5;

public class MethodTest9 {
	public static void main(String[] args) {
		int p1[] = { 20, 10, 14, 30};
		printArray(p1);

		int[] result = updateArray1(p1);
		printArray(result);
		printArray(p1);

		System.out.println("-------------------");

		updateArray2(p1);
		printArray(p1);
	}

	public static void printArray(int[] p2) {
		for(int d : p2)
			System.out.printf("%d ", d);
		System.out.printf("\n");
	}

	static int[] updateArray1(int[] p2) {
		int[] result = new int[p2.length];
		for(int i=0; i < result.length;i++)
			result[i] = p2[i] * 2;
		return result;
	}

	static void updateArray2(int[] p3) {
		for(int i=0; i < p3.length;i++)
			p3[i] = p3[i] * 2;
	}
}

updateArray1은 새 배열을 만들어서 반환한다.
그래서 원래 배열 p1은 그대로 남는다.

반면 updateArray2는 전달받은 배열 자체를 직접 수정한다.
그래서 메서드가 끝난 뒤 원본 p1의 값이 바뀐다.

핵심 포인트

둘 다 “배열 값을 2배로 만든다”는 점은 같지만
결과는 다르다.

  • updateArray1 → 원본 유지
  • updateArray2 → 원본 변경

문제에 따라 원본을 남겨야 할 수도 있고,
원본을 바로 바꿔도 될 수도 있기 때문에 이 차이를 알아야 한다.



7-6. main(String[] args)

개념

main 메서드의 String[] args는 그냥 외우는 문법이 아니다.
프로그램 실행 시 전달되는 문자열들을 받는 문자열 배열 매개변수다.

즉, 프로그램을 실행할 때 넘긴 값들이
args 배열에 들어온다고 이해하면 된다.

예제: MethodTest7

package day5;

public class MethodTest7 {
	public static void main(String[] args) {
		System.out.println("main() 수행시작");
		System.out.println(args.length);
		System.out.println("main() 수행종료");
	}
}

// 출력결과
// 실행 시 넘긴 문자열 개수만큼 숫자가 출력됨

이 예제는 전달받은 문자열 개수가 몇 개인지 보여준다.
즉, args가 실제로 배열처럼 들어온다는 점을 가장 단순하게 확인하는 예제다.

예제: MethodTest7_1

package day5;

public class MethodTest7_1 {
	public static void main(String[] args) {
		String result="";
		for(int i=0; i <args.length; i++)
			result = result + args[i];
		System.out.println(result);
	}
}

// 출력결과 예시
// 실행 시 Java Is Fun 을 넘기면
// JavaIsFun

이 코드는 실행할 때 받은 문자열들을 이어 붙여서 출력한다.

예제: MethodTest7_2

package day5;

public class MethodTest7_2 {
	public static void main(String[] args) {
		int result=0;
		for(int i=0; i <args.length; i++)
			result = result + Integer.parseInt(args[i]);
		System.out.println(result);
	}
}

// 출력결과 예시
// 실행 시 10 20 30 을 넘기면
// 60

이 코드는 전달받은 문자열을 숫자로 바꾼 뒤 더한다.

헷갈리기 쉬운 부분

args는 숫자 배열이 아니라 문자열 배열이다.
그래서 "10", "20"을 바로 더하는 것이 아니라
먼저 Integer.parseInt()로 숫자로 바꿔야 한다.




[응용 예제 / 실습]

응용 예제 - 2차원 배열 출력 코드를 메서드로 분리하기

문제에서 무엇을 하려는지

이 예제는 2차원 배열을 출력하는 코드를 따로 메서드로 빼서,
같은 기능을 여러 번 반복해서 사용할 수 있게 만드는 연습이다.
즉, 중복되는 출력 코드를 정리하고,
필요할 때마다 다시 호출하는 흐름을 익히는 것이 핵심이다.



이 예제에서 사용된 개념

  • 메서드 선언
  • 메서드 호출
  • 2차원 배열
  • 배열 매개변수
  • 이중 for문
  • 향상된 for문



코드 흐름

먼저 5행 3열짜리 2차원 배열을 만든다.
처음에는 배열 안에 값이 들어 있지 않으므로 0으로 채워진 상태다.

이 상태를 printTwoArray(nums) 메서드로 한 번 출력한다.
그다음 중첩 반복문을 사용해서 배열 안에 값을 채운다.
이후 다시 printTwoArray(nums)를 호출해서 바뀐 배열 상태를 출력한다.

즉, 이 예제는
배열을 채우는 코드와 배열을 출력하는 코드를 나눠서,
출력 기능만 따로 메서드로 분리한 구조를 보여준다.

같은 2차원 배열을 출력하더라도,
출력 로직을 메서드로 빼 두면 필요할 때마다 다시 사용할 수 있다는 점이 중요하다.

코드 예제

예제: MethodTest10_1

package day5;

public class MethodTest10_1 {

	public static void main(String[] args) {
		int[][] nums = new int[5][3];
		int num = 1;

		printTwoArray(nums);

		System.out.println();
		for (int j = 0; j < nums[0].length; j++) {
			for (int i = j; i < nums.length - j; i++)
				nums[i][j] = num++;
		}

		printTwoArray(nums);
	}

	static void printTwoArray(int[][] nums) {
		for (int[] rowData : nums) {
			for (int elem : rowData)
				System.out.print(elem + "\t");
			System.out.println();
		}
	}
}

// 출력결과
// 0	0	0
// 0	0	0
// 0	0	0
// 0	0	0
// 0	0	0
//
// 1	0	0
// 2	6	0
// 3	7	9
// 4	8	0
// 5	0	0

헷갈리기 쉬운 부분

이 예제에서 중요한 것은 숫자를 어떻게 채우는지보다,
출력 기능을 왜 따로 메서드로 뺐는지를 보는 것이다.

printTwoArray(nums)가 없다면 같은 출력문을 두 번 직접 써야 한다.
하지만 메서드로 분리해 두면 한 줄로 다시 호출할 수 있다.

또 printTwoArray(int[][] nums)처럼 2차원 배열도 매개변수로 받을 수 있다는 점도 함께 확인해야 한다.
즉, 메서드는 단순한 값 하나만 받는 것이 아니라 배열 전체도 받을 수 있다.




참고

이번 예제들은 대부분 static 메서드로 작성되어 있다.
왜 이렇게 호출할 수 있는지는 객체지향에서 다시 정리하면 된다.

이 정도면 일반 메서드는
왜 필요한지 → 어떻게 읽는지 → 가장 쉬운 형태 → 반환값 → 매개변수 → 활용
순서로 자연스럽게 복습할 수 있다.

0개의 댓글