오늘 공부한 내용
mini pms 프로그램 예제 프로젝트 06 버전을 수행하면서 메서드가 필요한 이유에 대해 배웠습니다.
메서드
메서드란 코드를 관리하기 쉽고 재사용하기 쉽도록 기능 단위로 묶어 놓는 문법을 말한다. 메서드명과 변수 선언을 말하는 메서드 시그니처(method signature)와 메서드 블록을 뜻하는 메서드 몸체(method body)로 구성되어 있다.
메서드 문법
- 메서드 선언 문법:
[리턴값의 타입] 함수명(파라미터선언, ...){명령어들}
- 리턴값(return value)의 타입: 함수 블록에 들어 있는 명령어를 수행 완료한 후 그 결과로 놓이는 값의 타입
- 파라미터(parameter) 선언: 함수 블록을 실행할 때 외부로부터 받은 값을 저장할 변수 선언
- 매서드 사용 문법:
[리턴값을 받을 변수] = 메서드명(아규먼트)
- 아규먼트: 메서드 블록에 들어 있는 명령을 실행하기 위해 넘겨주는 값, 즉 파라미터 변수에 넘겨주는 값을 말한다. 파라미터 변수의 타입과 개수와 순서에 맞게 값을 넘겨주어야 한다. 그렇지 않으면 컴파일 오류가 발생한다.
- 리턴값을 받을 변수: 매서드 블록을 실행한 후 리턴되는 값을 받을 변수이다. 매서드가 값을 리턴할 때 선언하지만, 메서드가 값을 리턴한다 하더라도 받고싶지 않으면 변수를 선언하지 않아도 된다. 이때 리턴되는 값은 버려진다. 값을 리턴하지 않는 메서드에 대해 변수를 선언하면 컴파일 오류가 발생한다.
- 아규먼트와 파라미터
- 아규먼트(argument): 메서드를 호출할 때 넘겨주는 값
- 파라미터(parameter): 아규먼트를 받는 변수
메서드 실행 순서
1
2
3
4
5
6
7
static void myMethod() {
System.out.println("이 메서드는 어떠한 값도 리턴하지 않습니다.")
}
public static void main(String[] args){
hello();
}
위의 코드는 다음과 같은 순서로 실행된다.
- hello() 메서드의 블록으로 간다.
- 메서드 바디를 실행한다.
- 다시 원래의 위치로 돌아온다.
- 다음 줄을 실행한다.
메서드의 종류
클래스 vs 인스턴스 메서드
클래스 메서드(정적 메서드)
- 클래스에 소속되어 있고, 모든 인스턴스에 대해 사용할 수 있다.
- static이 붙는다.
- 로드된 클래스를 바탕으로 호출하는 메서드
클래스명.메소드(아규먼트);
인스턴스 메서드:
인스턴스에 대해 사용할 수 있다.
- static이 붙지 않는다.
- 만들어진 인스턴스를 바탕으로 호출하는 메서드
레퍼런스명.메서드(아규먼트);
클래스 로드란? byte 코드로 되어 있는 클래스 코드(xxx.class)를 해당 OS가 해석 가능한 바이너리 코드로 번역되어 메모리로 올라가 쓰일(used) 준비 상태로 되는 것
리턴값과 파라미터 여부에 따른 메서드 종류
파라미터란? 메서드를 실행할 때 사용할 값을 외부로부터 받기 위해 선언한다. 메서드를 실행할 때 생성되고 메서드 실행이 끝나면 제거된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 1. 리턴값(X), 파라미터(X)
void 매서드명() {
문장1;
문장2;
}
// 2. 리턴값(X), 파라미터(O)
void 메서드명(변수선언1, 변수선언2, ...) {
문장1;
문장2;
}
// 3. 리턴값(O), 파라미터(X)
리턴타입 메서드명() {
문장1;
문장2;
return 리턴값;
}
// 4. 리턴값(O), 파라미터(O)
리턴타입 메서드명(변수선언1, 변수선언2, ...) {
문장1;
문장2;
return 리턴값;
}
- 리턴 타입은 반드시 한 개만 가능하다.
- 만약 여러 개의 값을 리턴하고 싶다면, 배열에 담거나 객체에 담아야 한다.
- 리턴 명령을 실행하면 메서드 실행을 종료시킨다.
- 메서드를 리턴한 후에 작업을 수행할 수 없다.
- 메서드가 값을 리턴한다고 해서 반드시 리턴값을 변수에 받아야 하는 것은 아니다.
- 값을 받는 변수가 없으면 리턴 값은 버려진다.
가변 파라미터 vs 배열 파라미터
가변 파라미터는 메서드에서 0개 이상의 값을 받을 때 선언하는 방식으로 메서드 내부에서는 배열처럼 사용한다.
가변 파라미터 | 배열 파라미터 | |
---|---|---|
낱개의 값을 줄 수 있는가? | O | X |
값을 배열에 담아서 전달할 수 있는가? | O | O |
해당 파라미터를 여러개 선언할 수 있는가? | X | X |
어느 순서에도 파라미터를 선언할 수 있는가? | X (맨 뒤에 와야함) | O |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
static void hello1(String... names) {
for (int i = 0; i < names.length; i++){
System.out.printf("%s님 반갑습니다.\n", names[i]);
}
}
static void hello2(String[] names) {
for (int i =0; i < names.length; i++) {
System.out.printf("%s님 반갑습니다.\n", names[i]);
}
}
public static void main(String[] args) {
hello1(); // names 배열의 개수 0
hello1("monica"); // 1
hello1("monica", "juan"); // 2
hello1("monica", "juan", "maria"); // 3
// 배열 직접 넣기
String[] arr = {"daniella", "rosalina", "julio", "lucia"};
hello1(arr); //4
}
매서드 추출(Extract Method)
메서드 추출은 가장 많이 사용되는 리팩터링 기법 중 하나이다. 특정 메서드가 장황할 때 그룹으로 묶고 그 코드를 빼내 새로운 메서드로 작성한다. 메서드를 쪼개고 나서 목적을 잘 표현하는 이름으로 정의해야 한다. 매서드명은 보통 명령형 동사로 시작한다. (ex) addMember(), getMember(), listMember()
) 물론 toLowerCase()
와 같이 동사로 시작하지 않는 경우도 있기는 하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
메인메서드 {
System.out.print("번호? ");
pno[psize] = Integer.valueOf(keyboardScan.nextLine());
System.out.print("프로젝트명? ");
ptitle[psize] = keyboardScan.nextLine();
System.out.print("내용? ");
pcontent[psize] = keyboardScan.nextLine();
}
// 메서드 사용 후
// 코드가 직관적이고 유지보수하기 쉽다.
메인메서드 {
//..
ptitle[psize] = promptString("프로젝트명? ");
pcontent[psize] = promptString("내용? ");
//..
}
static String promptString(String title) {
System.out.print(title);
return keyboardScan.nextLine();
}
임시변수를 메서드 호출로 대체해라!
수식의 결과를 저장하는 임시변수가 있는 경우, 수식을 빼내 새로운 메서드로 생성하고 내용을 넣는다. 다른 메서드에서도 수식을 정의한 메서드를 추출할 수 있게 된다.
1
2
3
4
5
6
7
String input = prompt("번호? ");
no[count] = Integer.parseInt(input);
no[count] = Integer.parseInt(prompt("번호? "));
// 먼저 메소드가 실행되고 리턴값을 숫자로 바꾸고 저장한다.
// prompt는 App이라는 같은 도구함에 있다.
// parseInt는 다른 도구함(Integer)에 있기 때문에 적어줘야 한다.