// 계산1int a = 1;
int b = 2;
System.out.println(a + "+" + b + " 연산 수행");
int sum1 = a + b;
System.out.println("결과1 출력: " + sum1);
// 계산2int x = 10;
int y = 20;
System.out.println(x + "+" + y + " 연산 수행");
int sum2 = x + y;
System.out.println("결과2 출력: " + sum2);
계산1과 계산2의 구조가 완전히 동일하다. 변수 이름과 값만 다를 뿐이다. 이 연산을 100곳에서 써야 한다면 100번 반복해야 하고, 출력 형식을 바꾸려면 100곳을 모두 수정해야 한다.
수학에서 add(a, b) = a + b라는 함수를 정의해두면 add(1, 2), add(5, 6)처럼 여러 번 호출해 사용할 수 있다. 자바는 이 개념을 메서드(Method)라는 이름으로 언어에 통합했다.
2. 메서드 구조
메서드는 메서드 선언(Method Declaration)과 메서드 본문(Method Body)으로 구성된다.
제어자 반환타입 메서드이름(매개변수 목록) {
메서드 본문
}
publicstaticintadd(int a, int b) {
int sum = a + b;
return sum;
}
구성 요소
예시
의미
제어자
public static
접근 범위와 호출 방식을 지정한다. 지금은 항상 이 두 키워드를 함께 쓴다
반환 타입
int
메서드가 실행 후 돌려주는 값의 타입
메서드 이름
add
이 이름으로 메서드를 호출한다
매개변수
int a, int b
호출할 때 전달하는 입력값. 메서드 안에서만 유효한 지역 변수다
메서드 본문
{ ... }
실제 실행될 코드 블록. 호출하는 쪽은 내용을 몰라도 된다
public은 다른 클래스에서도 호출할 수 있다는 뜻이고, static은 객체를 생성하지 않고 호출할 수 있는 정적 메서드라는 뜻이다. 두 키워드의 상세한 내용은 이후 클래스·객체 편에서 다룬다.
매개변수(Parameter): 메서드를 정의할 때 선언하는 변수. "중간에서 전달하는 변수"라는 의미다.
인수(Argument): 메서드를 호출할 때 넘기는 실제 값. "들어가는 수"라는 의미다.
호출할 때 인수의 타입, 순서, 개수가 매개변수와 일치해야 한다. 실무에서는 두 용어를 혼용하는 경우가 많다.
4. 메서드 호출 흐름
add(5, 10) 호출이 어떻게 처리되는지 단계별로 따라가 보자.
// 1: add 메서드를 5, 10을 전달하며 호출int sum1 = add(5, 10);
// 2: 매개변수 a=5, b=10 대입 후 메서드 실행publicstaticintadd(int a=5, int b=10) {
int sum = a + b; // 3: sum = 15return sum; // 4: 15 반환
}
// 5: 반환값 15가 호출 위치를 대체, sum1에 저장int sum1 = 15;
메서드 호출이 끝나면 매개변수 a, b와 지역 변수 sum은 모두 소멸된다. 스택 프레임이 제거되기 때문이다.
5. void와 return
매개변수도, 반환 타입도 없는 메서드가 있다.
publicstaticvoidprintHeader() {
System.out.println("= 프로그램을 시작합니다 =");
return; // void의 경우 생략 가능
}
publicstaticvoidprintFooter() {
System.out.println("= 프로그램을 종료합니다 =");
}
매개변수가 없는 경우: 선언에서 괄호 안을 비운다 — printHeader(). 호출할 때도 인수 없이 printHeader();로 호출한다.
반환 타입이 없는 경우: void를 반환 타입 자리에 쓴다. void 메서드에서 return은 메서드를 즉시 종료하는 역할을 하며, 마지막 줄에서는 생략할 수 있다.
void 메서드의 반환값을 변수에 받으려 하면 컴파일 오류가 발생한다. 반환 타입이 void이므로 반환할 값 자체가 없다.
6. 반환 타입과 return의 규칙
모든 경로에서 return이 있어야 한다
반환 타입이 있는 메서드는 실행 가능한 모든 경로에서 return이 보장되어야 한다.
// 컴파일 오류 — else 분기에서 return이 없다publicstaticbooleanodd(int i) {
if (i % 2 == 1) {
returntrue;
}
// i가 짝수면 return에 도달하지 못함 → java: missing return statement
}
// 올바른 버전publicstaticbooleanodd(int i) {
if (i % 2 == 1) {
returntrue;
} else {
returnfalse;
}
}
return을 만나면 즉시 메서드를 빠져나간다
void 메서드에서 return을 조기 탈출에 활용할 수 있다. 이후 코드를 실행하지 않고 메서드를 종료한다.
publicstaticvoidcheckAge(int age) {
if (age < 18) {
System.out.println(age + "살, 미성년자는 출입이 불가능합니다.");
return; // 여기서 메서드 종료, 아래 코드는 실행되지 않는다
}
System.out.println(age + "살, 입장하세요.");
}
7. 자바는 항상 값을 복사해서 전달한다
자바에서 가장 중요한 원칙 중 하나다.
자바는 항상 변수의 값을 복사해서 대입한다.
변수 복사
int num1 = 5;
int num2 = num1; // num1의 값 5를 읽어 복사 → num2에 5 저장
num2 = 10; // num2만 10으로 변경System.out.println("num1=" + num1); // num1=5System.out.println("num2=" + num2); // num2=10
num2 = num1은 num1 자체가 num2로 들어가는 것이 아니다. num1에 있는 값 5를 읽어 num2에 복사하는 것이다. 이후 두 변수는 독립적이다.
인수의 타입이 매개변수 타입보다 작으면 자동으로 변환된다. int < long < double 순으로 더 큰 타입으로 자동 확장된다.
int number = 100;
printNumber(number); // int → double 자동 형변환publicstaticvoidprintNumber(double n) {
System.out.println("숫자: " + n); // 숫자: 100.0
}
메서드를 호출할 때 인수를 매개변수에 대입하는 것도 결국 변수 대입이므로, 일반 변수 대입의 형변환 규칙이 그대로 적용된다.
10. 메서드 오버로딩
같은 기능을 수행하지만 매개변수의 개수나 타입이 다른 메서드를 여러 개 정의할 수 있다. 이것을 메서드 오버로딩(Overloading)이라 한다.
publicstaticintadd(int a, int b) {
return a + b;
}
// 매개변수 개수가 다르다 — 오버로딩 성공publicstaticintadd(int a, int b, int c) {
return a + b + c;
}
// 매개변수 타입이 다르다 — 오버로딩 성공publicstaticdoubleadd(double a, double b) {
return a + b;
}
입금·출금 로직이 각자의 메서드로 분리되어, 출금 조건이 바뀌면 withdraw()만 수정하면 된다. 이런 리팩토링을 메서드 추출(Extract Method)이라 한다. 코드 재사용이 목적이 아니어도 충분히 가치 있다. 메서드의 이름이 코드를 읽기 좋게 만드는 문서 역할을 한다.
13. 메서드 사용의 장점
장점
설명
코드 재사용
같은 기능을 여러 곳에서 호출만 하면 된다
가독성
의미 있는 이름을 붙인 메서드는 코드를 읽는 데 도움을 준다
모듈성
큰 프로그램을 작고 관리 가능한 단위로 분리할 수 있다
유지보수
변경이 필요할 때 해당 메서드 하나만 수정하면 된다
추상화
호출하는 쪽은 구현 방식을 몰라도 된다
테스트 용이성
메서드 단위로 독립적인 테스트가 가능하다
메서드를 잘 설계하는 기준으로 단일 책임 원칙(Single Responsibility Principle)이 있다. 하나의 메서드는 하나의 일만 해야 한다는 원칙이다. 메서드에 "그리고"가 붙는 설명이 필요하다면 분리를 고려할 때다.