본문 바로가기
JAVA BASE/OOP(객체지향 프로그래밍)

02-2. [자바] 변수와 메서드(재귀호출)

by staticClass 2020. 12. 9.

2020/12/09 - [JAVA BASE/05. OOP(객체지향 프로그래밍)] - 02-1. [JAVA] 변수와 메서드

자바에서 메서드를 만드는 방법이 궁금하다면 위에 링크 클릭! 👏


메서드의 호출

메서드를 정의해도 호출해야 구현부{}의 문장이 수행된다. 메서드를 호출 하는 방법은 다음과 같다.😃

메서드이름(값1, 값2, ...);    // 메서드를 호출하는 방법
      ↓        ↓        ↓       ↓
print99danAll();         // void print99danAll()을 호출
int result = add(3, 5);  // int add(int x, int y)를 호출하고, 결과를 result에 저장

인자(argument)와 매개변수(parameter)

메서드를 호출할 때 괄호()안에 지정해준 값들을 '인자(argument)' 또는 '인수'라고 하는데
인자의 개수와 순서는 호출된 메서드에 선언된 매개변수와 일치해야한다.

//메서드 매개변수로 add는 int형 데이터를 2개 받겠다고 선언했음
int add(int x, int y) {
    result = x + y;
}

public static void main(String args[]) { 
    // 메서드 호출 
    int sumValue = add(3, 5);    // add는 int형 데이터 2개를 받겠다고 했기 때문에 인수로 int타입인 3과 5를 넣어 주어야함
}

만일 메서드에 선언된 매개변수의 개수보다 적거나, 많거나, 타입이 다르면 컴파일 에러가 발생한다.

int result = add(1);        // 에러. 메서드에 선언된 매개변수와 개수가 다름.
int result = add(1, 2, 3);    // 에러. 메서드에 선언된 매개변수와 개수가 다름.
int reuslt = add(1.0, 1.0); // 에러. 메서드에 선언된 매개변수의 타입이 다름.

메서드의 실행흐름

class Calculator {
    long add(long a, long b) { return a+b; }           // 덧셈 메서드
}

class CalcTest{
    public static void main(String args[]) {
        Calculator calc = new Calculator();
        calc.add(1L, 2L);    //add 메서드 호출
    }
}
① main 메서드에서 add 메서드를 호출, 호출시 지정한 1L, 2L이 add의 매개변수 a, b에 각각 대입된다.
② 메서드 add의 괄호{} 안에 있는 문장들이 순서대로 수행된다.
③ 메서드 add의 모든 문장이 실행되거나 return문을 만나면, 호출한 메서드(main메서드)로 
되돌아와 main메서드의 이후 문장을 실행한다.👍

재귀호출(recursive call)

메서드의 내부에서 메서드 자신을 다시 호출하는 것을 '재귀호출(recursive call)'이라 하고
재귀호출을 하는 메서드를 '재귀 메서드' 라고 한다.

void method() {
    method();    // 재귀호출, 메서드 자신을 호출한다.
}

어떻게 메서드가 자기자신을 호출할 수 있는지 의아하겠지만, 메서드 입장에서는
자기 자신을 호출하는 것과 다른 메서드를 호출하는 것은 차이가 없다.
하지만 위의 코드처럼 재귀호출뿐이면, 무한히 자기 자신을 호출하기 때문에
무한반복에 빠지게 된다. 무한반복문이 조건문과 함께 사용되어야 하는 것처럼,
재귀호출도 조건문이 필수적으로 따라다닌다.

void method(int n) {
    if(n == 0) return;
    System.out.println(n);
    method(--n);
}

위 코드는 n이 0 일때 재귀호출을 중단하게 된다.
재귀 호출은 반복문과 유사한 점이 많고 대부분의 재귀호출을 반복문으로 작성하는 것 또한 가능하다.
반복문과 다르게 재귀호출은 매개변수 복사, 종료, 복귀할 주소저장 등이 추가로 필요하기 때문에
반복문보다 재귀호출의 수행시간이 더 오래 걸린다.
그렇다면 왜 반복문 대신 재귀호출을 사용해야 할까? 그 이유는 재귀호출이 주는 논리적 간결함 때문이다.
아무리 효율적이어도 알아보기 힘들게 작성하는 것보다 비효율적이어도 알아보기 쉽게 작성해야
논리적 오류가 발생할 확률도 줄고 나중에 수정하기도 좋다.

대표적 예를 들자면 팩토리얼(factorial)을 구하는 것이다.
팩토리얼은 한 숫자가 1이 될 때까지 1씩 감소시켜가면서 계속해서 곱해 나가는 것이다.

// 재귀호출
class factorial(int n) {
    if(n == 1) return 1;
    return n * factorial(n-1);
}
// 반복문
class factorial(int n) {
    int result = 1;
    while(n!=0) result *= n--;
    return result;
}

재귀호출을 이용 하는것이 반복문을 이용하는 것 보다 확실히 짧고 이해가 쉬워졌다.

클래스 메서드(static메서드)와 인스턴스 메서드

변수와 마찬가지로 메서드 앞에 static이 붙어있으면 클래스 메서드, 아니면 인스턴스 메서드이다.
클래스 메서드도 클래스변수처럼 객체를 생성하지 않고 '클래스이름.메서드이름(매개변수)'와 같은 식의
호출이 가능하다. 반면 인스턴스 메서드는 반드시 객체를 생성해야만 호출할 수 있다.
그렇다면 어느 경우에 static을 사용해서 클래스 메서드로 정의해야 하는 것일까?

인스턴스 메서드는 작업을 수행하는데 인스턴스 변수를 필요로 하는 메서드이다.
그런데 이 인스턴스 변수는 객체를 생성해야만 만들어지므로 인스턴스 메서드 역시 인스턴스를
생성해야만 호출할 수 있는 것이다.

반면에 인스턴스 변수를 사용하지 않아도 매개변수만으로 작업이 가능한 메서드를
클래스 메서드(static 메서드)로 정의한다.

같은 클래스의 멤버 간에는 별도의 인스턴스를 생성하지 않고도 서로 참조, 호출이 가능하다.
단, 클래스(static) 멤버가 인스턴스 멤버를 호출하려면 인스턴스를 생성해야한다.

인스턴스 멤버 > 인스턴스 변수/메서드 , static 변수/메서드 모두 호출가능
클래스(static) 멤버 > static변수/메서드 호출가능, 인스턴스 변수/메서드 호출하려면 객체생성 해야함.

 


재귀호출.. 증말 어렵다💨
차라리 익숙해지게 사용할 일이 많았으면 좋겠다
토이프로젝트를 시작하게 되면 재귀호출을 자주 
사용해서 익숙해져야겠다.🤢

댓글