점프 투 자바 - 객체 지향 프로그래밍 5-3 메서드
매개변수(parameter) : 메서드에 전달된 입력값을 저장하는 변수
인수(arguments) : 메서드를 호출할 때 전달하는 입력값
public class Sample{
int sum(int a, int b){ // a,b는 매개변수
return a+b;
}
public static void main(String[] args) {
Sample sample = new Sample();
int c = sample.sum(3,4); // 3,4는 인수
System.out.println(c);
}
}
1. 입력값과 리턴값이 모두 있는 메서드
int sum(int a, int b) {
return a+b;
}
sum 메서드의 입출력 자료형은 다음과 같다.
- 입력값 : int 자료형 a, int 자료형 b
- 리턴값 : int 자료형
< 입력값과 리턴값이 있는 메서드를 호출하는 방법 >
리턴값_받을_변수 = 객체.메서드명(입력인수1, 입력인수2, ...)
< sum 메서드의 사용 예 >
Sample sample = new Sample();
int result = sample.sum(3,4);
sample.sum(3,4) 호출 후 리턴값을 저장하는 result의 자료형은 int로 해야만 한다.
왜냐하면 sum 메서드의 리턴 자료형이 int로 되어있기 때문이다.
2. 입력값이 없는 메서드
String say(){
return "Hi";
}
say 메서드의 입출력 자료형은 다음과 같다.
- 입력값 : 없음
- 리턴값 : String 자료형
say라는 이름의 메서드를 만들었지만 입력인수를 나타내는 괄호 안이 비어있다.
이렇듯 입력인수가 없을 경우에는 괄호 안을 비워 놓으면 된다.
< 입력값이 없고 리턴값만 있는 메서드를 호출하는 방법 >
리턴값_받을_변수 = 객체.메서드명()
< say 메서드 사용 예 >
public class Sample{
String say(){
return "Hi";
}
public static void main(String[] args) {
Sample sample = new Sample();
String a = sample.say();
System.out.println(a); // "Hi" 출력
}
}
say 메서드를 쓰기 위해서는 say()처럼 괄호 안에 아무런 값도 넣지 않고 써야 한다.
3. 리턴값이 없는 메서드
void sum(int a, int b){
System.out.println(a+"과 "+b+"의 합은 "+(a+b)+"입니다.");
}
sum 메서드의 입출력 자료형은 다음과 같다.
- 입력값 : int 자료형 a, int 자료형 b
- 리턴값 : void (리턴값 없음)
< 리턴값이 없는 메서드를 호출하는 방법 >
객체.메서드명(입력인수1, 입력인수2, ...)
< sum 메서드 사용 예 >
public class Sample {
void sum(int a, int b) {
System.out.println(a+"과 "+b+"의 합은 "+(a+b)+"입니다.");
}
public static void main(String[] args) {
Sample sample = new Sample();
sample.sum(3,4);
}
}
실제로 메서드를 호출해보면 "3과 4의 합은 7입니다."라는 문자열이 출력된다.
해당 문장이 출력됐는데 왜 리턴값이 없다는 걸까?
이 부분이 초보자들이 혼동하는 부분이기도 한데,
** System.out.println문은 메서드 내에서 사용되는 문장일 뿐 리턴값은 없다!!
리턴값은 오직 return 명령어로만 반환이 가능하다.
4. 입력값과 리턴값이 모두 없는 메서드
void say() {
System.out.println("Hi");
}
say 메서드 입출력 자료형은 다음과 같다.
- 입력값 없음
- 리턴값 void
< 입력값도, 리턴값도 없는 메서드를 호출하는 방법 >
객체.메서드명()
< say 메서드 사용 예 >
public class Sample {
void say() {
System.out.println("Hi");
}
public static void main(String[] args) {
Sample sample = new Sample();
sample.say();
}
}
출력값은 Hi 이지만 리턴값이 없을 뿐이다.
return의 또다른 쓰임
문자열을 출력한다는 것과 리턴값이 있다는 것은 전혀 다른 말이다.
여기서 쓰인 return은 메서드를 즉시 빠져나가는 역할을 한다.
public class Sample {
void sayNick(String nick) {
if ("바보".equals(nick)) {
return;
}
System.out.println("나의 별명은 "+nick+" 입니다.");
}
public static void main(String[] args) {
Sample sample = new Sample();
sample.sayNick("야호");
sample.sayNick("바보"); // 출력되지 않는다.
}
}
출력 결과 : 나의 별명은 야호 입니다.
- return 문만 단독으로 사용하여 메서드를 빠져나가는 이 방법은 리턴 자료형이 void인 메서드만 가능하다.
- 리턴 자료형이 명시되어 있는 메서드에서 return 문만 작성하면 컴파일 오류가 발생한다.
- return문을 단독으로 사용하여 메서드를 빠져나가는 방법은 실제 프로그래밍에서 자주 사용한다.
메서드 내에서 선언된 변수의 효력 범위
메서드 안에서 사용하는 변수의 이름을 메서드 밖에서 사용한 이름과 동일하게 사용한다면 어떻게 될까?
public class Sample {
void varTest(int a) {
a++;
}
public static void main(String[] args) {
int a = 1;
Sample sample = new Sample();
sample.varTest(a);
System.out.println(a);
}
}
varTest 메서드에서 a의 값을 1만큼 증가시켰으니 2가 출력되어야 할 것 같지만 막상 프로그램을 실행해보면
1이라는 결괏값이 나온다.
그 이유는 메서드에서 사용한 매개변수는 메서드 안에서만 쓰이는 변수이기 때문이다.
즉, void varTest (int a) 라는 문장에서 매개 변수 a는 메서드 안에서만 쓰이는 변수이지
메서드 밖의 변수 a가 아니라는 뜻이다.
메서드에서 쓰이는 매개 변수의 이름과 메서드 밖의 변수 이름이 같더라도 서로 전혀 영향을 주지 않는다.
그렇다면 varTest라는 메서드를 이용해서 main 메서드 외부의 a의 값을 1만큼 증가시킬 수 있는 방법은 없을까?
varTest메서드에 return문을 이용하면 된다.
public class Sample {
int varTest(int a) {
a++;
return a;
}
public static void main(String[] args) {
int a = 1;
Sample sample = new Sample();
a = sample.varTest(a);
System.out.println(a);
}
}
varTest 메서드는 입력으로 들어온 값을 1만큼 증가시켜 리턴한다.
따라서 a = sample.varTest(a) 처럼 작성하면 a의 값은 다시 varTest 메서드의 리턴값으로 대입된다.
즉 1만큼 증가된 값으로 a의 값이 변경된다.
이번에는 varTest 입력값이 int 자료형이 아닌 객체인 경우를 살펴보자.
메서드에 값을 전달하는 것과 객체를 전달하는 것에는 큰 차이가 있다.
객체를 메서드의 입력으로 넘기고 메서드가 객체의 속성값(객체 변수 값)을 변경한다면
메서드 수행 이후에도 객체는 변경된 속성값을 유지한다.
public class Sample {
int a; // 객체변수 a
void varTest(Sample sample) {
sample.a++;
}
public static void main(String[] args) {
Sample sample = new Sample();
sample.a = 1;
sample.varTest(sample);
System.out.println(sample.a);
}
}
int 자료형인 변수 a를 Sample 클래스의 객체 변수로 선언했다.
varTest 메서드는 Sample 클래스의 객체를 입력받아 해당 객체의 a값을 1만큼 증가시켰다.
main 메서드에서는 varTest 메서드 호출 시 Sample 클래스의 객체인 sample을 전달하도록 수정했다.
이렇게 하고 프로그램을 실행해보면 sample 객체의 객체 변수 a의 값이 원래는 1이었는데
varTest 메서드 실행 후 1만큼 증가되어 2가 출력되는 것을 확인할 수 있다.
여기서 주목해야 하는 부분은 varTest 메서드의 입력 파라미터가
값이 아닌 Sample 클래스의 객체라는 데 있다.
이렇게 메서드가 객체를 전달 받으면 메서드 내의 객체는 전달받은 객체 그 자체로 수행된다.
따라서 입력으로 전달받은 sample 객체의 객체 변수 a의 값이 증가하게 되는 것이다.
위의 예제에 sample.varTest(sample); 라는 문장이 있다.
sample 객체를 이용하여 varTest라는 메서드를 호출할 경우 굳이 sample 객체를 전달할 필요가 없다.
왜냐하면 전달하지 않더라도 varTest 메서드는 this라는 키워드를 이용하여 객체에 접근할 수 있기 때문이다.
void varTest() {
this.a++;
} 와 같이 this를 사용하여 varTest 메서드를 수정할 수 있다.