9-1. 메서드 시작
Method1.java
package method;
public class Method1 {
public static void main(String[] args) {
// 계산1
int a = 1;
int b = 2;
System.out.println(a + "+" + b + " 연산 수행");
int sum1 = a + b;
System.out.println("결과1 출력:" + sum1);
// 계산2
int x = 10;
int y = 20;
System.out.println(x + "+" + y + " 연산 수행");
int sum2 = x + y;
System.out.println("결과2 출력:" + sum2);
}
}
- 같은 연산을 두번 수행
- 수학의 함수 개념을 차용해서 사용
- 함수를 한번 정의해두면 재사용이 가능
- 필요할 때마다 함수명으로 호출해서 사용
9-2. 메서드 사용
메서드(Method)는 함수의 한 종류
Method1.java
package method;
public class Method1Ref {
public static void main(String[] args) {
// 계산1
int sum1 = add(5, 10);
System.out.println("결과1 출력:" + sum1);
// 계산2
int sum2 = add(15, 20);
System.out.println("결과2 출력:" + sum2);
}
// add 메서드
public static int add(int a, int b) {
System.out.println(a + "+" + b + " 연산 수행");
int sum = a + b;
return sum;
}
}
- 메서드 정의 (메서드를 정의한다)
public static int add(int a, int b) {
System.out.println(a + "+" + b + " 연산 수행");
int sum = a + b;
return sum;
}
- 메서드 선언(Method Declaration)
public static int add(int a, int b)
메서드 이름, 반환 타입, 매개변수(파라미터) 목록을 포함
- public static
- public : 다른 클래스에서 호출할 수 있는 메서드 (접근 제어)
- static : 객체를 생성하지 않고 호출할 수 있는 정적 메서드 (나중에 자세히)
- int add(int a, int b)
- int : 반환 타입 정의, 메서드 실행 결과를 반환할 때 사용
- add : 메서드명, 메서드 호출 시 이 이름을 사용
- (int a, int b) : 매개변수 = 파라미터(parameter). 메서드 호출할 때 전달하는 입력 값 정의, 이 변수들은 해당 메서드 안에서만 사용
- 메서드 본문(Method Body)
{
System.out.println(a + "+" + b + " 연산 수행");
int sum = a + b;
return sum;
}
- 메서드를 호출하면 메서드 본문이 순서대로 실행
- 메서드 본문은 블랙박스 => 메서드를 호출하는 곳에서는 메서드 선언은 알지만 메서드 본문은 모름
- 메서드 실행 결과를 반환하려면 return문을 사용
- 메서드 호출
int sum1 = add(5, 10);
/*
public static int add(5, 10){
int sum = 5 + 10;
return sum(15);
*/
int sum2 = add(15, 20);
/*
public static int add(15, 20){
int sum = 15 + 20;
return sum(35);
*/
- 메서드 호출이 끝나면 더 이상 해당 메서드가 사용한 메모리를 낭비할 이유가 없기 때문에, 파라미터 변수와 메서드 안에서 정의된 int sum 모두 제거된다.
- 메서드 호출과 용어 정리
호출: call("hello", 20) // 인수, 인자
메서드 정의: int call(String str, int age) // 매개변수, 파라미터
메서드 호출할 때,
- 메서드에 넘기는 값이 매개변수(파라미터)의 타입이 맞아야 한다.
- 또, 매개변수(파라미터)의 순서와 갯수도 맞아야 한다.
인자 = 인수(Argument)
- "hello", 20 처럼 메서드에 넘기는 값
- '인'과 '수'의 합성어로 '들어가는 수'라는 의미 => 메서드 내부로 들어가는 값
매개변수(Parameter)
- 메서드를 정의할 때 선언한 변수 => String str, int age
- '매개'와 '변수'의 합성어로 '중간에서 전달하는 변수'라는 의미 => 메서드 호출부와 메서드 내부 사이에서 값을 전달하는 역할을 하는 변수
9-3. 메서드 정의
public static int add(int a, int b) {
// 메서드 본문, 실행 코드
}
제어자 반환타입 메서드이름(매개변수 목록) {
}
- 제어자(Modifier): public , static 과 같은 부분
- 반환 타입(Return Type): 메서드가 실행된 후 반환하는 데이터의 타입을 지정
메서드가 값을 반환하지 않는 경우, 없다는 뜻의 void 를 사용 예) void print(String str) - 메서드 이름(Method Name): 메서드의 이름(무언가를 동작하는데 사용하기에 일반적으로 동사로 시작). 메서드를 호출하는데 사용
- 매개변수(Parameter): 메서드 내부에서 사용할 수 있는 변수. 매개변수는 옵션. 입력값이 필요 없는 메서드는 매개변수를 지정하지 않아도 된다. 예) add()
- 메서드 본문(Method Body): 실제 메서드의 코드가 위치. 중괄호 {} 사이에 코드를 작성.
Method2.java - 매개변수가 없거나 반환타입이 없는 경우
package method;
public class Method2 {
public static void main(String[] args) {
printHeader(); // 인수를 비워두고 호출
System.out.println("프로그램이 동작합니다.");
printFooter(); // 반환 타입이 없으므로 반환 값을 받으면 안됨
}
public static void printHeader() { // 매개변수를 비워두고 정의
System.out.println("= 프로그램을 시작합니다 =");
return; // void의 경우 생략 가능
}
public static void printFooter() { // 반환 타입이 없으면 void로 정의
System.out.println("= 프로그램을 종료합니다 =");
}
}
- return을 만나면 해당 메서드는 종료된다.
9-4. 반환 타입
MethodReturn1.java - 반환 타입이 있으면 반드시 return을 사용해서 값을 반환해야 한다.
package method;
public class MethodReturn1 {
public static void main(String[] args) {
boolean result = odd(2);
System.out.println(result);
}
public static boolean odd(int i) {
if (i % 2 == 1) {
return true;
} else {
return false;
}
}
}
MethodReturn2.java - return문을 만나면 그 즉시 메서드를 종료한다.
package method;
public class MethodReturn2 {
public static void main(String[] args) {
checkAge(10);
checkAge(20);
}
public static void checkAge(int age) {
if (age < 18) {
System.out.println(age + "살, 미성년자는 출입이 불가능합니다.");
return; // 메서드를 빠져나간다.
}
System.out.println(age + "살, 입장하세요.");
}
}
9-5. 메서드 호출과 값 전달1
"자바는 항상 변수의 값을 복사해서 대입한다. "
MethodValue0.java - 변수와 값 복사
package method;
public class MethodValue0 {
public static void main(String[] args) {
int num1 = 5;
int num2 = num1;
num2 = 10;
System.out.println("num1=" + num1);
System.out.println("num2=" + num2);
}
}
MethodValue1.java - 메소드 호출과 값 복사
package method;
public class MethodValue1 {
public static void main(String[] args) {
int num1 = 5;
System.out.println("1. changeNumber 호출 전, num1: " + num1);
changeNumber(num1);
System.out.println("4. changeNumber 호출 후, num1: " + num1);
}
public static void changeNumber(int num2) {
System.out.println("2. changeNumber 변경 전, num2: " + num2);
num2 = num2 * 2;
System.out.println("3. changeNumber 변경 후, num2: " + num2);
}
}
9-6. 메서드 호출과 값 전달2
MethodValue2.java - 메소드 호출과 이름이 같은 변수
package method;
public class MethodValue2 {
public static void main(String[] args) {
int number = 5;
System.out.println("1. changeNumber 호출 전, number: " + number);
changeNumber(number);
System.out.println("4. changeNumber 호출 후, number: " + number);
}
public static void changeNumber(int number) {
System.out.println("2. changeNumber 변경 전, number: " + number);
number = number * 2;
System.out.println("3. changeNumber 변경 후, number: " + number);
}
}
- main()도 사실은 메서드
- 각각의 메서드 안에서 사용하는 변수는 서로 완전히 분리된 다른 변수이다. (이름이 같아도)
MethodValue3.java - 메소드 호출과 값 반환받기
package method;
public class MethodValue3 {
public static void main(String[] args) {
int num1 = 5;
System.out.println("changeNumber 호출 전, num1: " + num1); // 출력: 5
num1 = changeNumber(num1); // 값 반환
System.out.println("changeNumber 호출 후, num1: " + num1); // 출력: 10
}
public static int changeNumber(int num2) {
num2 = num2 * 2;
return num2;
}
}
9-7. 메서드와 형변환
MethodCasting1.java - 명시적 형변환
메서드를 호출하는데 인자와 매개변수의 타입이 맞지 않을 때,
package method;
public class MethodCasting1 {
public static void main(String[] args) {
double number = 1.5;
// printNumber(number); // double을 int로 대입하므로 컴파일 오류
// 오류 => java: incompatible types: possible lossy conversion from double to int
printNumber((int) number); // 명시적 형변환을 사용해 double을 int로 변환
}
public static void printNumber(int n) {
System.out.println("숫자: " + n);
}
}
MethodCasting2.java - 자동 형변환
int < long < double
package method;
public class MethodCasting2 {
public static void main(String[] args) {
int number = 100;
printNumber(number);
}
public static void printNumber(double n) {
System.out.println("숫자: " + n); // 숫자: 100.0
}
}
- double형 매개변수(파라미터)에 int형 인수를 전달하는데 문제없이 잘 동작
9-8. 메서드 오버로딩
다음과 같은 메서드를 같은 이름인 add로 만들고 싶다.
- 두 수를 더하는 메서드
- 세 수를 더하는 메서드
오버로딩 성공
add(int a, int b)
add(int a, int b, int c)
add(double a, double b)
add(int a, double b) // 매개변수의
add(double a, int b) // 순서가 다름
- 메서드 오버로딩(Overloading) : 매개변수가 다르고 같은 이름의 메서드를 여러개 정의하는 것.
과적(과하게 물건을 담았다.)
오버로딩 규칙
- 메서드 이름이 같아도, 매개변수의 타입 및 순서가 다르면 오버로딩 가능. 반환 타입은 인정하지 않음
오버로딩 실패
int add(int a, int b)
double add(int a, int b)
용어: 메서드 시그니처(method signature)
- 메서드 시그니처 = 메서드 이름 + 매개변수 타입(순서)
- 자바에서 메서드를 구분할 수 있는 고유한 식별자나 서명을 뜻한다.
- 메서드 이름이 같아도 메서드 시그니처가 다르면 다른 메서드로 간주
- 반환 타입은 시그니처에 포함되지 않는다.
Overloading1.java
package method;
public class Overloading1 {
public static void main(String[] args) {
System.out.println("1: " + add(1, 2));
System.out.println("2: " + add(1, 2, 3));
}
// 첫 번째 add 메서드: 두 정수를 받아서 합을 반환한다.
public static int add(int a, int b) {
System.out.println("1번 호출");
return a + b;
}
// 두 번째 add 메서드: 세 정수를 받아서 합을 반환한다.
// 첫 번째 메서드와 이름은 같지만, 매개변수 목록이 다르다.
public static int add(int a, int b, int c) {
System.out.println("2번 호출");
return a + b + c;
}
}
Overloading2.java
package method;
public class Overloading2 {
public static void main(String[] args) {
myMethod(1, 1.2);
myMethod(1.2, 2);
}
public static void myMethod(int a, double b) {
System.out.println("int a, double b");
}
public static void myMethod(double a, int b) {
System.out.println("double a, int b");
}
}
Overloading3.java
package method;
public class Overloading3 {
public static void main(String[] args) {
System.out.println("1: " + add(1, 2));
System.out.println("2: " + add(1.2, 1.5));
}
// 첫 번째 add 메서드: 두 정수를 받아서 합을 반환한다.
public static int add(int a, int b) {
System.out.println("1번 호출");
return a + b;
}
// 두 번째 add 메서드: 두 실수를 받아서 합을 반환한다.
// 첫 번째 메서드와 이름은 같지만, 매개변수의 유형이 다르다.
public static double add(double a, double b) {
System.out.println("2번 호출");
return a + b;
}
}
- 첫번재 add 메서드가 없으면 자동 형변환 발생해 add(double a, double b)가 호출된다.
메서드 사용의 장점
- 코드 재사용: 메서드는 특정 기능을 캡슐화하므로, 필요할 때마다 그 기능을 다시 작성할 필요 없이 해당 메서드를 호출함으로써 코드를 재사용할 수 있다.
- 코드의 가독성: 이름이 부여된 메서드는 코드가 수행하는 작업을 명확하게 나타내므로, 코드를 읽는 사람에게 추가적인 문맥을 제공한다.
- 모듈성: 큰 프로그램을 작은, 관리 가능한 부분으로 나눌 수 있다. 이는 코드의 가독성을 향상시키고 디버깅을 쉽게 만든다.
- 코드 유지 관리: 메서드를 사용하면, 코드의 특정 부분에서 문제가 발생하거나 업데이트가 필요한 경우 해당 메서드만 수정하면 된다. 이렇게 하면 전체 코드 베이스에 영향을 주지 않고 변경 사항을 적용할 수 있다.
- 재사용성과 확장성: 잘 설계된 메서드는 다른 프로그램이나 프로젝트에서도 재사용할 수 있으며, 새로운 기능을 추가하거나 기존 기능을 확장하는 데 유용하다. => ex) 라이브러리
- 추상화: 메서드를 사용하는 곳에서는 메서드의 구현을 몰라도 된다. 프로그램의 다른 부분에서는 복잡한 내부 작업에 대해 알 필요 없이 메서드를 사용할 수 있다.
- 테스트와 디버깅 용이성: 개별 메서드는 독립적으로 테스트하고 디버그할 수 있다. 이는 코드의 문제를 신속하게 찾고 수정하는 데 도움이 된다.
9-9. 문제와 풀이1
MethodEx1.java
package method.ex;
public class MethodEx1 {
public static void main(String[] args) {
int a = 1;
int b = 2;
int c = 3;
int sum = a + b + c;
double average = sum / 3.0;
System.out.println("평균값: " + average);
int x = 15;
int y = 25;
int z = 35;
sum = x + y + z;
average = sum / 3.0;
System.out.println("평균값: " + average);
}
}
MethodEx1Ref.java
package method.ex;
public class MethodEx1Ref {
public static void main(String[] args) {
System.out.println("평균값: " + average(1, 2, 3));
System.out.println("평균값: " + average(15, 25, 35));
}
public static double average(int a, int b, int c) {
int sum = a + b + c;
return sum / 3.0;
}
}
MethodEx2.java
package method.ex;
public class MethodEx2 {
public static void main(String[] args) {
String message = "Hello, world!";
for (int i = 0; i < 3; i++) {
System.out.println(message);
}
for (int i = 0; i < 5; i++) {
System.out.println(message);
}
for (int i = 0; i < 7; i++) {
System.out.println(message);
}
}
}
MethodEx2Ref.java
package method.ex;
public class MethodEx2Ref {
public static void main(String[] args) {
repeat(3); // repeat("Hello, world!", 3);
repeat(5);
repeat(7);
}
public static void repeat(int n) {
System.out.println(n+"번 반복");
for (int i = 0; i < n; i++) {
System.out.println("Hello, world!");
}
}
}
MethodEx3.java
package method.ex;
public class MethodEx3 {
public static void main(String[] args) {
int balance = 10000;
// 입금 1000
int depositAmount = 1000;
balance += depositAmount;
System.out.println(depositAmount + "원을 입금하였습니다. 현재 잔액: " + balance + "원");
// 출금 2000
int withdrawAmount = 2000;
if (balance >= withdrawAmount) {
balance -= withdrawAmount;
System.out.println(withdrawAmount + "원을 출금하였습니다. 현재 잔액: " + balance + "원");
} else {
System.out.println(withdrawAmount + "원을 출금하려 했으나 잔액이 부족합니다.");
}
System.out.println("최종 잔액: " + balance + "원");
}
}
MethodEx3Ref.java
package method.ex;
public class MethodEx3Ref {
public static void main(String[] args) {
int balance = 10000;
balance = deposit(balance, 1000);
balance = withdraw(balance, 2000);
System.out.println("최종 잔액: " + balance + "원");
}
public static int deposit(int balance, int amount) {
balance += amount;
System.out.println(amount + "원을 입금하였습니다. 현재 잔액: " + balance + "원");
return balance;
}
public static int withdraw(int balance, int amount) {
if (balance >= amount) {
balance -= amount;
System.out.println(amount + "원을 출금하였습니다. 현재 잔액: " + balance + "원");
} else {
System.out.println(amount + "원을 출금하려 했으나 잔액이 부족합니다.");
}
return balance;
}
}
9-10. 문제와 풀이2
MethodEx4.java
package method.ex;
import java.util.Scanner;
public class MethodEx4 {
public static void main(String[] args) {
int balance = 0;
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("------------------------------------");
System.out.println("1.입금 | 2.출금 | 3.잔액 확인 | 4.종료");
System.out.println("------------------------------------");
System.out.print("선택: ");
int option = scanner.nextInt();
if (option == 1){
System.out.print("입금액을 입력하세요: ");
int amount = scanner.nextInt();
balance = deposit(balance, amount);
} else if (option == 2) {
System.out.print("출금액을 입력하세요: ");
int amount = scanner.nextInt();
balance = withdraw(balance, amount);
} else if (option == 3) {
System.out.println("현재 잔액: " + balance + "원");
} else if (option == 4) {
System.out.println("시스템을 종료합니다.");
break;
}
}
}
public static int deposit(int balance, int amount) {
balance += amount;
System.out.println(amount + "을 입금했습니다. 현재 잔액: " + balance);
return balance;
}
public static int withdraw(int balance, int amount) {
if (balance >= amount) {
balance -= amount;
System.out.println(amount + "을 출금했습니다. 현재 잔액: " + balance);
} else {
System.out.println(amount + "을 출금하려 했으나 잔액이 부족합니다.");
}
return balance;
}
}
강의 풀이 => switch문을 사용
public static void main(String[] args) {
int balance = 0;
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("---------------------------------");
System.out.println("1.입금 | 2.출금 | 3.잔액 확인 | 4.종료");
System.out.println("---------------------------------");
System.out.print("선택: ");
int choice = scanner.nextInt();
int amount;
switch (choice) {
case 1:
System.out.print("입금액을 입력하세요: ");
amount = scanner.nextInt();
balance = deposit(balance, amount);
break;
case 2:
System.out.print("출금액을 입력하세요: ");
amount = scanner.nextInt();
balance = withdraw(balance, amount);
break;
case 3:
System.out.println("현재 잔액: " + balance + "원");
break;
case 4:
System.out.println("시스템을 종료합니다.");
return;
default:
System.out.println("올바른 선택이 아닙니다. 다시 선택해주세요.");
}
}