수학의 함수처럼 필요한 기능을 미리 정의해두고 필요할 때마다 호출해서 사용하는 함수의 한 종류
//메서드의 정의
public static int add(int a, int b) {
System.out.println(a + "+" + b + " 연산 수행");
int sum = a + b;
return sum;
}
위와 같은 메서드를 만들면 a+b를 수행하는 함수를 만들 수 있다
int sum1 = add(5, 10); //add라는 메서드를 숫자 5,10을 전달하면서 호출한다.
int sum1 = 15; //add(5, 10)이 실행된다. 실행 결과는 반환 값은 15이다.
//sum1에 15 값이 저장된다.
메서드를 호출할 때는 다음과 같이 메서드에 넘기는 값과 매개변수(파라미터)의 타입이 맞아야 한다. 물론 넘기는 값과 매개변수(파라미터)의 순서와 갯수도 맞아야 한다.
호출: call("hello", 20) 메서드 정의: int call(String str, int age)
여기서 "hello"
, 20
처럼 넘기는 값을 영어로 Argument(아규먼트), 한글로 인수 또는 인자라 한다. 실무에서는 아규먼트, 인수, 인자라는 용어를 모두 사용한다.
메서드를 정의할 때 선언한 변수인 String str
, int age
를 매개변수, 파라미터라 한다. 메서드를 호출할 때 인수를 넘기면, 그 인수가 매개변수에 대입된다.
실무에서는 매개변수, 파라미터 용어를 모두 사용한다.
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() {
System.out.println("= 프로그램을 종료합니다 =");
}
}
printHeader()
,printFooter()
메서드는 매개변수가 없고, 반환 타입도 없다.
public static void printHeader()
와 같이 매개변수를 비워두고 정의하면 된다.printHeader();
와 같이 인수를 비워두고 호출하면 된다.public static void printHeader()
와 같이 반환 타입을 void
로 정의하면 된다.printHeader();
와 같이 반환 타입이 없으므로 메서드만 호출하고 반환 값을 받지 않으면 된다.String str = printHeader();
반환 타입이 void
이기 때문에 이렇게 반환 값을 받으면 컴 파일 오류가 발생한다.모든 메서드는 항상 return
을 호출해야 한다. 그런데 반환 타입 void
의 경우에는 예외로 printFooter()
와 같 이 생략해도 된다. 자바가 반환 타입이 없는 경우에는 return
을 마지막줄에 넣어준다. 참고로 return
을 만나면 해 당 메서드는 종료된다.
반환 타입이 있으면 반드시 값을 반환해야 한다. 반환 타입이 있는 메서드는 반드시
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;
} //이렇게 해야지 오류가 발생하지 않는다.
*/
}
}
이 코드에서
if
조건이 만족할 때는true
가 반환되지만, 조건을 만족하지 않으면 어떻게 될까? 조건을 만족하지 않 은 경우에는return
문이 실행되지 않는다. 따라서 이 코드를 실행하면return
문을 누락했다는 다음과 같은 컴파일 오류가 발생한다.
java: missing return statement
else문을 통해 return이 수행되어서 오류가 해결된다
return
문을 만나면 그 즉시 해당 메서드를 빠져나간다.
자바는 항상 변수의 값을 복사해서 대입한다.
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);
}
}
실행 결과
1. changeNumber 호출 전, num1: 5
2. changeNumber 변경 전, num2: 5
3. changeNumber 변경 후, num2: 10
4. changeNumber 호출 후, num1: 5
결과적으로 매개변수
num2
의 값만 10으로 변경되고num1
의 값은 변경되지 않고 기존 값인 5로 유지된다. 자바는 항 상 값을 복사해서 전달하기 때문에num2
의 값을 바꾸더라도num1
에는 영향을 주지 않는다.
package method;
public class MethodCasting1 {
public static void main(String[] args) {
double number = 1.5;
// printNumber(number); //double을 int에 대입하므로 컴파일 오류.
printNumber((int) number); //명시적 형변환을 사용하여 double을 int로 변환
}
public static void printNumber(int n){
System.out.println("숫자: " + n);
}
}
메서드를 호출하는데 인자와 매개변수의 타입이 맞지 않다면 아래와 같은 오류가 발생한다.
java: incompatible types: possible lossy conversion from double to int
오류나는 원인
printNumber(number) //number는 1.5 실수 printNumber(1.5) //메서드를 호출하기 전에 number 변수의 값을 읽음 void printNumber(int n=1.5) //int형 매개변수 n에 double형 실수인 1.5를 대입 시도, 컴파일 오 류
오류해결을 위해서는 명시적 형변환을 사용해야 한다.
printNumber((int) number); // 명시적 형변환을 사용해 double을 int로 변환 printNumber(1); // (double) 1.5 -> (int) 1로 변환 void printNumber(int n=1) //int형 파라미터 변수 n에 int형 1을 대입
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);
}
}
double형 매개변수에 int를 전달하는 것은 아무런 무리없이 작동한다.
다음과 같이 자동 형변환이 동작한다.
printNumber(number); // number는 int형 100 printNumber(100); //메서드를 호출하기 전에 number 변수의 값을 읽음
void printNumber(double n=100) //double형 파라미터 변수 n에 int형 값 100을 대입
void printNumber(double n=(double) 100) //double이 더 큰 숫자 범위이므로 자동 형변환 적용
void printNumber(double n=100.0) //자동 형변환 완료
메서드를 호출할 때는 전달하는 인수의 타입과 매개변수의 타입이 맞아야 한다. 단 타입이 달라도 자동 형변환이 가능한 경우에는 호출할 수 있다.
이름이 같고 매개변수가 다른 메서드를 여러개 정의하는 것으로 오버로딩은 번역하면 과적인데, 과하게 물건을 담았다는 뜻이다. 같은 이름의 메서드를 여러개 정의했다고 이해하면 된다
add(int a, int b)
add(int a, int b, int c)
add(double a, double b)
int add(int a, int b)
double add(int a, int b)
메서드 시그니처 = 메서드 이름 + 매개변수 타입(순서)
메서드 시그니처는 자바에서 메서드를 구분할 수 있는 고유한 식별자나 서명을 뜻한다. 메서드 시그니처는 메서드의 이 름과 매개변수 타입(순서 포함)으로 구성되어 있다. 쉽게 이야기해서 메서드를 구분할 수 있는 기준이다. 자바 입장에서 는 각각의 메서드를 고유하게 구분할 수 있어야한다. 그래야 어떤 메서드를 호출 할 지 결정할 수 있다.
따라서 메서드 오버로딩에서 설명한 것 처럼 메서드 이름이 같아도 메서드 시그니처가 다르면 다른 메서드로 간주한다. 반환 타입은 시그니처에 포함되지 않는다. 방금 오버로딩이 실패한 두 메서드를 보자. 두 메서드는 add(int a, int b)
로 메서드 시그니처가 같다. 따라서 메서드의 구분이 불가능하므로 컴파일 오류가 발생한다.
본인의 타입에 최대한 맞는 메서드를 찾아서 실행하고, 그래도 없으면 형 변환 가능한 타입의 메서드를 찾아서 실행한다.