메서드 (Methods)
1. 메서드 개요
만약 내가 여러번 반복해서 쓰고 싶은 코드들이 있다면...?
매번 복붙하는 것보다... 코드를 한 곳에 모아놓고 그 코드만 불러들여서 쓴다면...?
훨씬 효율적이다 !
>> 이럴 때 활용할 수 있는게 메서드이다.
함수? 메서드?
- 함수 : 독립적으로 실행될 수 있는 코드 조각
- 메서드 : "특정 클래스"와 연결되어 그 클래스 객체에서 수행하는 기능
쉽게 말해
점점 길어지고 중복된 기능인 부분을 따로 빼내고, 이름을 붙여 메서드를 만든다.
* main 메서드
: 프로그램의 시작점(entrypoint)를 정의하는 메서드
public class Main {
public class void main(String[] args) {
System.out.println("이것도 일종의 메서드");
}
}
- 메서드 정의하기
public class Main {
public static(제어자) int(반환타입) addTwo(이름) (int a, int b(매개변수)) {
return a+b;(리턴값)
}
}
- 제어자 : 접근 제어자, 정적 제어자 (클래스에서 좀더 다룸)
- 반환타입 : 이 메서드의 결과로 만들어지는 데이터의 자료형 / void는 반환값이 없는 메서드임 (return이 굳이 필요하지 않음)
- 이름(식별자) : 변수의 이름처럼 이 메서드를 부를 때 사용할 이름
- 매개변수(parameter) : 메서드에 전달할 데이터를 나타내는 변수
- return ~ : 이 메서드가 최종적으로 무엇을 반환할지
1) 매개변수(parameter) >> "입력값"
: 메서드로 전달될 값들을 정의하기 위해 사용.
- 개수는 필요한 만큼 사용가능 & 매개변수가 필요 없는 메서드는 비워두어도 됨.
2) 반환 return >> "출력값"
: 코드를 실행해서 돌려주고 싶은 결과를 만들고 return 뒤에 작성.
- return 자체가 메서드 내에서 여러개 나올 수 있음. 코드 실행 중 만나면 결과 반환~
** 반환 vs 출력 다르다!!!!!~!~!
>> 출력을 하는 System.out.println() 메서드는 반환이 아니라 출력만 한다.
// 내부의 코드가 입력을 읽는다. 문자열을 반환해주는 메서드임
String line = scanner.nextLine();
// 내부의 코드가 출력을 한다. 반환은 하지 않음.
System.out.println(line);
3) 메서드 호출
: 메서드 이름을 가지고 호출한다.
public class Main {
public static int addTwo(int a, int b) {
// 3) 전달된 파라미터 값을로 메서드 실행과 리턴
// 5) 전달된 파라미터 값으로 메서드 실행과 리턴
return a + b;
}
public static int subTwo(int a, int b) { //7) 전달된 파라미터 값으로 메서드 실행과 리턴
return a - b;
}
public static void main(String[] args) { //1)main에서 시작
// ...
int result2 = subTwo(addTwo(4, 5), addTwo(2, 3));
// 2) subTwo()메서드 안의 첫번째 인자 addTwo() 메서드 호출
// 4) subTwo()메서드 안의 두번째 인자 addTwo() 메서드 호출
// 6) 3, 5의 리턴값을 가지고 subTwo()메서드 호출
// 8) subTwo()메서드의 리턴값을 result2 변수에저장
System.out.println(result2);
}
}
2. 재귀 함수
: 자기 자신을 호출하는 메서드.
ex. 팩토리얼 (계승) : n부터 1까지의 자연수를 전부 곱한 수
인자를 하나 줄인 다음 다시 팩토리얼 함수 호출...
factRec(n)
= n * factRec(n-1)
= n * (n-1) * factRec(n-2)
...
= n * (n-1) * ... * 2 * 1
- 재귀함수는 성능이 아닌 가독성과 편의성.
public static int factorial(int n) {
// 종료 조건을 먼저 언급하는 것이 좋다.
// 종료되는 조건 : 0이나 1이면 1을 반환
if (n == 1 || n == 0) {
System.out.println(n);
return 1;
} else { // 아니면 n*f(n-1)을 반환한다.
System.out.println(n);
return n*factorial(n-1);
}
}
ex2. 피보나치 수열
// 피보나치 수열은
// F(0) = 0
// F(1) = 1
// F(2) = 2
// F(n) = F(n-1) + F(n-2)인 수의 나열이다.
// 음이 아닌 정수n을 인자로 받아 n번째 피보나치 수를 반환하는 메서드를 구현하시오.
public static int fibo(int n) {
if (n==0||n==1) {
return n;
} else {
return fibo(n-1) + fibo(n-2);
}
}
3. 메서드 오버로딩
: 비슷한 역할을 하는 두 메서드일 때 인자의 자료형을 달리 메서드를 정의한다..
int a = 1, b = 2;
long c = 1, d = 2;
addInt(a, b);
addInt(c, d);
// 오류발생. c,d는 long 자료형이기 때문에
// 더 작은 int 자료형에 들어가기 위해서는 형변환이 되어야 함.
addLong(a, b);
addLong(c, d);
public static int addInt(int a, int b) {
return a + b;
}
public static long addLong(long a, long b) {
return a + b;
}
>> 이 때 굳이 이름을 다르게 하는 것이 아니라 같은 이름을 가지고 여러 조건을 정의할 수 있다~!~!
public static int add(int a, int b) {
return a + b;
}
public static long add(long a, long b) {
return a + b;
}
>> 이렇게 만들어주면 메서드 호출 단계에서 전달받는 인자의 자료형에 따라 어떤 메서드를 사용할지 정해진다.
?? int + int 는 범위를 벗어날 수 있으니 반환 타입을 두가지로 하는건 어떨까...???
- 반환 자료형은 메서드를 구분하는 용도로는 활용이 불가하다.
public static int add(int a, int b) { // 반환 타입만 다른 메서드 둘
return a + b;
}
public static long add(int a, int b) {
return (long) a + b;
}
int a=1, b=2;
add(a, b);
// 자료형이 int인 a,b인 인자로 구성된 메서드가 둘 다 해당되기 때문에... 불가능!!!!
// 인자의 자료형에 따라 메서드를 호출하는데... 두 메서드의 인자 자료형이 같기 때문에 컴퓨터가 선택 불가능
* 가장 대표적인 메서드 오버로딩 예시 > println();
println() {}
println(boolean x) {}
println(char x) {}
println(char[] x) {}
println(double x) {}
println(float x) {}
println(int x) {}
println(long x) {}
println(java.lang.Object x) {}
println(java.lang.String x) {}
4. 가변인자 Varargs (Variable-length arguments lists)
: 임의 갯수의 인자를 받을 수 있는 기능
상황에 따라서... 인자의 갯수를 미리 알지 못하다면 어떻게 할까...?
ex. String.format();
String.format("%d개의 인자", 2);
String.format("%d개의 인자도 받지요%c", 3, '!');
String.format("인자가 %d개라고 다를게 있을까요? %s %s", 4, "아마", "괜찮을걸요");
String.format(String s, Object...obj);
- 메서드 내부에서는 배열처럼 활용 가능.
- 호출 시 인자를 여러개 전달 가능.
- 배열도 전달 가능
- 가변인자와 다른 인자를 사용하고 싶다면? 가변인자를 가장 나중에 넣어야 함. (어디까지가 가변인자가 가져갈 인자인지 파악하기 어렵기 때문!)
public static int varNumSum(int... numbers) {
int sum = 0;
// 마치 배열 쓰듯이 사용
for (int i = 0; i < numbers.length; i++) {
sum += numbers[i];
}
return sum;
}
System.out.println(varIntSum(1, 2, 3, 4, 5)); // 원하는 갯수만큼 인자 전달 가능
int[] numbers = {1, 2, 3, 4};
System.out.println(varNumSum(numbers)); // 배열도 전달 가능
public static void repeatStrings(String line, int... counts) { //꼭 마지막에 가변인자 선언
for (int count : counts) {
for (int i = 0; i < count; i++) {
System.out.print(line);
}
System.out.println();
}
}
** 메서드 오버로딩과 함께 사용할 시 주의할 점!
- 배열로 가변인자 전달이 가능하기 때문에~ 메서드의 매개변수 형태가 모호할 수 있음 (컴파일 오류)
public static int varNumSum(int... numbers) {
// ...
}
public static int varNumSum(int[] numbers) {
// ...
} // 둘 중 어떤 메서드를 불러들여야할지 모호함..
+ 만약, 같은 자료형으로 인자를 설정한다면...? 이때도 모호하다
public static int varNumSum(int... numbers) {
// ...
}
public static int varNumSum(int base, int...numbers){
// ...
} // 모든 인자의 자료형이 int이기 때문에 이것도 어떤 메서드를 호출할지가 모호함.
// 오류
System.out.println(varNumSum(1, 2, 3, 4, 5));
// 정상
System.out.println(varNumSum(1, new int[]{2, 3, 4, 5}));
System.out.println(varNumSum(new int[]{1, 2, 3, 4, 5}));
'Programming > Java' 카테고리의 다른 글
객체지향 프로그래밍 (1) | 2023.11.28 |
---|---|
클래스 (Class) (1) | 2023.11.28 |
제어문 (Control Statements) (1) | 2023.11.22 |
연산자 (Operators) (0) | 2023.11.21 |
변수와 자료형 (Variables and Types) (1) | 2023.11.20 |