똑같은 코드를 여기저기 복사·붙여넣기 하고 있나요? 메서드(method)는 그 코드에 이름을 붙여 한 번 만들고 몇 번이든 재사용하게 해줘요. 프로그램을 "역할별로 쪼개는" 첫걸음입니다.
main이 static인 이유와 어떻게 연결되는지 감을 잡아요.메서드(method)는 "어떤 일을 하는 코드 묶음에 이름을 붙여 둔 것"이에요. 이름을 한 번 붙여 두면, 나중에 그 이름만 부르면(호출하면) 안에 든 코드가 통째로 실행돼요. 수학의 함수 f(x)와 비슷하다고 보면 돼요. 다른 언어에서 말하는 "함수(function)"를 자바에서는 메서드라고 부릅니다.
아래는 우리가 이미 써 본 System.out.println("...")도 사실 메서드 호출이라는 걸 보여줘요. println이라는 "출력하는 메서드"를 부른 거죠. 이번 장에서는 이 메서드를 직접 만드는 법을 배웁니다.
메서드의 기본 뼈대는 다음과 같아요. 크게 ①반환타입 ②메서드이름 ③매개변수목록 ④본문(그리고 return) 네 부분으로 나뉩니다.
반환타입 메서드이름(매개변수목록) {
// 실행할 코드 (본문)
return 값; // 반환타입이 void가 아니면 값을 돌려줌
}
실제 예로, 두 정수를 더해 결과를 돌려주는 메서드를 만들어 볼게요.
int add(int a, int b) {
int sum = a + b;
return sum;
}
int sum처럼 메서드 안(또는 { } 블록 안)에서 선언한 변수예요. 그 메서드가 실행되는 동안에만 잠깐 살아 있다가 메서드가 끝나면 사라져요. 그래서 다른 메서드에서는 이 sum을 볼 수 없어요 — 각 메서드는 자기만의 작업 공간을 갖는 셈이죠.| 부분 | 예시 | 설명 |
|---|---|---|
| ① 반환타입 | int | 이 메서드가 돌려줄 값의 타입. 정수를 돌려주니 int. 아무것도 안 돌려주면 void. |
| ② 메서드이름 | add | 호출할 때 부를 이름. 변수 이름 규칙과 같고, 보통 동사로 짓고 소문자로 시작해요(카멜케이스). |
| ③ 매개변수목록 | int a, int b | 메서드가 받아 쓸 입력값을 담는 변수. 없으면 괄호 안을 비워요 (). |
| ④ 본문 · return | return sum; | { } 안이 실제로 하는 일. return이 결과값을 바깥으로 돌려줘요. |
getUserName). 중간이 낙타 등처럼 볼록해서 붙은 이름이죠. 자바에서 메서드·변수 이름은 이 관례를 따라요.int이면 return으로 반드시 정수 값 하나를 돌려줘야 해요. 반환타입이 void면 돌려줄 값이 없으니 return 값;을 쓰지 않습니다.메서드를 정의했다고 실행되는 게 아니에요. 이름을 불러야(호출해야) 그 안의 코드가 돌아가요. 앞에서 만든 add를 호출해 볼게요.
int result = add(3, 4); // add 메서드 호출, 3과 4를 넘김
System.out.println(result); // 7
여기서 호출할 때 넘긴 3, 4를 인자(argument)라고 해요. 이 인자가 메서드 안의 매개변수(parameter) a, b로 순서대로 복사되어 들어가요. 즉 a = 3, b = 4가 됩니다.
add(3, 4)의 3과 4.int a, int b.
한 줄 정리: 보내는 쪽의 값 = 인자, 받는 쪽의 변수 = 매개변수. 인자가 매개변수 안으로 복사되어 들어가요.
이때 자바는 값을 "복사해서" 전달해요. 이걸 값에 의한 전달(pass by value)이라고 불러요. 그래서 메서드 안에서 매개변수를 바꿔도, 바깥의 원래 변수는 영향을 받지 않아요.
n = 5x = 5n은 안 바뀌어요.void addOne(int x) {
x = x + 1; // 복사본 x만 바뀜
}
int n = 5;
addOne(n);
System.out.println(n); // 여전히 5 (원본은 안 바뀜)
n은 그대로 5. (참조 타입은 조금 다르게 동작하는데, 그건 객체를 배우는 CH 10 이후에 자연스럽게 알게 돼요. 지금은 "기본형은 복사되어 넘어간다"만 챙기면 충분합니다.)return은 메서드의 결과값을 호출한 곳으로 돌려주는 명령이에요. 그리고 return을 만나는 순간 메서드는 즉시 종료돼요 — 그 아래 코드는 실행되지 않습니다.
int max(int a, int b) {
if (a > b) {
return a; // 여기서 끝. 아래로 안 내려감
}
return b;
}
return을 만나면 메서드가 바로 끝나기 때문에, 그 아래에 코드를 두면 도달할 수 없는 코드(unreachable)가 돼요. 실제로 컴파일 오류가 나기도 합니다.돌려줄 값이 없는 메서드도 있어요. "화면에 출력만 한다"처럼요. 이럴 땐 반환타입을 void로 씁니다. void는 "비어 있다"는 뜻이에요.
void sayHello(String name) {
System.out.println("안녕, " + name + "!");
// return 값; 없음
}
sayHello("자바"); // 출력: 안녕, 자바!
int, String 등. return 값;으로 결과를 돌려주고, 호출한 쪽에서 int r = add(3,4);처럼 값을 받아 쓸 수 있어요.void. 돌려주는 값이 없어요. 그래서 int r = sayHello("자바");처럼 값을 받으려 하면 오류예요. 다만 return;(값 없이)만 써서 메서드를 중간에 끝낼 수는 있어요.
정리: void는 "결과값이 없다"는 뜻이지 "return을 못 쓴다"는 뜻이 아니에요. 값 없는 return;으로 조기 종료는 가능합니다.
void printPositive(int x) {
if (x <= 0) {
return; // 값 없이 그냥 종료 (여기서 끝)
}
System.out.println(x + "는 양수예요.");
}
return 값; → 값을 돌려주며 종료 (반환타입 필요). return; → 값 없이 그냥 종료 (void에서 사용).오버로딩(overloading)은 같은 이름의 메서드를 여러 개 정의하는 거예요. 단, 조건이 있어요 — 매개변수의 타입이나 개수가 서로 달라야 합니다. 그러면 자바가 호출할 때 넘긴 인자를 보고 알맞은 버전을 알아서 골라 줘요.
int add(int a, int b) { // 정수 두 개
return a + b;
}
double add(double a, double b) { // 실수 두 개 (매개변수 타입이 다름)
return a + b;
}
int add(int a, int b, int c) { // 정수 세 개 (매개변수 개수가 다름)
return a + b + c;
}
위 세 개는 이름이 모두 add지만, 매개변수가 달라서 공존할 수 있어요. 호출하는 쪽은 이렇게 씁니다.
add(3, 4); // int add(int, int) → 7
add(3.5, 1.5); // double add(double, double) → 5.0
add(1, 2, 3); // int add(int, int, int) → 6
add(int,int) vs add(double,double). 가능!add(int,int) vs add(int,int,int). 가능!int add(int,int) vs double add(int,int). 불가능! 매개변수가 똑같으면 자바가 어느 걸 부를지 구분할 수 없어서 컴파일 오류가 나요.
핵심: 오버로딩은 매개변수(타입·개수·순서)로 구분해요. 반환타입은 구분 기준이 아니에요.
addInt, addDouble처럼 이름을 다 다르게 지으면 외울 게 많아져요. 오버로딩을 쓰면 "더한다 = add" 하나만 기억하면 되고, 나머지는 인자에 맞춰 자바가 골라 줘요. 실제로 System.out.println도 정수·문자열·실수를 모두 받는 오버로딩된 메서드랍니다.우리가 매번 쓴 시작점을 떠올려 봐요.
public static void main(String[] args) {
// 프로그램 시작
}
여기 붙은 static은 "객체를 만들지 않고, 클래스 이름만으로 바로 쓸 수 있는 메서드"를 뜻해요. 자바 프로그램이 시작될 때는 아직 객체가 하나도 없는 상태예요. 그런데 main이 static이라, 객체 없이도 바로 실행할 수 있어서 프로그램의 진입점이 될 수 있는 거예요.
main 메서드부터 실행하기로 약속돼 있어서, main이 바로 그 진입점이에요. 그래서 main이 없거나 형태가 틀리면 프로그램이 "어디서 시작할지 몰라" 실행되지 않아요.직접 만든 메서드도 static을 붙일 수 있어요. 그러면 같은 클래스의 main에서 객체를 만들지 않고 바로 호출할 수 있어요.
public class Calc {
static int add(int a, int b) { // static 메서드
return a + b;
}
public static void main(String[] args) {
int r = add(3, 4); // 객체 없이 바로 호출 가능
System.out.println(r); // 7
}
}
Math.max(1, 2). main도 이 부류예요."abc".length()처럼 어떤 객체에 붙어 동작해요.
지금은 "main이 static이라 객체 없이 시작된다"와 "static 메서드는 객체 없이 부른다" 정도만 챙기면 충분해요. 객체가 정확히 무엇이고 인스턴스 메서드가 왜 필요한지는 바로 다음 장(CH 10)에서 본격적으로 배웁니다.
int add(int a, int b){ return a+b; }return;으로 조기 종료만 가능.main이 static이라 프로그램이 객체 없이 시작돼요. (자세한 건 CH 10)