메서드(Method)

  • 특정 작업을 수행하는 일련의 문장들을 하나로 묶은 것

  • 수학의 함수와 유사

  • 메서드는 입력값과 출력값이 없을 수도 있으며, 모두 없을 수도 있음

  • 사용하는 이유

    • 높은 재사용성(reusability)

    • 중복된 코드의 제거

    • 프로그램 구조화



메서드의 선언(선언부 : method declaration, method header)

  • 반환타입(return type)

    • 작업 수행 결과(출력)인 반환값(return value)의 타입

    • 반환값이 없다면 void를 적어야 함

  • 메서드 이름(method name)

    • 변수의 명명규칙대로 작성

    • 특정 작업을 수행하므로 ‘add’처럼 동사인 경우가 많음

    • 이름만으로도 메서드의 기능을 쉽게 알 수 있도록 함축적이고 의미있게

  • 매개변수 선언(parameter declaration)

    • 메서드가 작업을 수행하기 위해 필요한 값들(입력)을 제공

    • 필요한 값의 개수만큼 변수를 선언, 각 변수의 구분은 콤마’,’

    • 변수 타입이 같아도 변수 타입 생략 불가

    • 개수 제한은 없지만, 값의 개수가 많으면 배열이나 참조변수 사용

    • 값을 전혀 입력받을 필요가 없다면 괄호 ( ) 안에 아무것도 적지 않을 것

/* 메서드 선언부 */
반환타입 메서드이름 (타입 변수명, 타입변수명, ...)



메서드의 구현(구현부 : method body)

  • 지역변수(local variable)

    • 메서드 내에 선언된 변수, 그 메서드 내에서만 사용

    • 서로 다른 메서드라면 같은 이름의 변수를 선언해도 됨

  • return문

    • 리턴타입이 ‘void가 아니라면’ 필수
  • return 반환값

    • 반환값을 전달

    • 반환타입과 일치하거나 적어도 자동형변환이 가능한 값

    • 반환값(출력)은 딱 1개만 가능함

/* 메서드 구현부 */
{
   // 메서드 호출시 수행될 코드
}



메서드 호출

  • 메서드는 호출해야만 동작함

    • main 메서드는 프로그램 실행시 자동적으로 호출됨
  • 호출 방법

    • 메서드이름(값1, 값2);

    • 값은 생략 가능

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

    • 인자(argument) : 호출할 때 괄호( )안에 지정된 값

    • 개수와 순서는 호출된 메서드에 선언된 매개변수와 일치해야 함

    • 메서드가 호출되면서 매개변수에 대입되므로, 인자의 타입은 매개변수의 타입과 일치하거나 자동 형변환이 가능해야 함

    • 예) int result = sunny(3, 5); //에서 3, 5 (원본)

  • 매개변수(parameter) : 호출한 인수가 복사되며 실제 메소드를 호출할 때 쓰이는 값

    • int sunny(int x, int y) {} //에서 x=3, y=3 (복사본)
  • 같은 클래스 내의 메서드끼리는 참조변수를 사용하지 않고도 서로 호출이 가능

  • static 메서드는 같은 클래스 내의 인스턴스 메서드를 호출할 수 없음

  • 메서드의 실행 흐름(같은 클래스 내의 메서드 호출)

    • 메인 메서드에서 호출시 인스턴스 생성을 해야 함

    • 메서드 호출(인자값)

    • 인자 → 매개변수로 복제되어 메서드 호출

    • 메서드 실행

    • 메서드 반환값 반환



return문

  • 현재 실행중인 메서드를 종료하고 호출한 메서드로 되돌아감

  • 반환값이 있을 때만 return을 썼지만, 원래는 다 써야함

    • void의 경우 컴파일러가 메서드의 마지막에 return;을 자동으로 찍어줌

    • 반환 타입이 void가 아닌 경우, return이 없으면 컴파일 에러(error : missing return statement)가 발생

  • 조건식을 넣을 경우 else나 끝에도 항상 return;을 넣어줌을 유의할 것

  • 반환값(return type)

    • return문의 반환값으로 주로 변수가 오지만, 식이 올 때도 있음(계산해서 값을 반환)



매개변수의 유효성 검사

  • 메서드의 구현부 { }를 작성할 때, 가장 먼저 해야하는 일이 매개변수의 값이 적절한 것인지 확인하는 것

  • 메서지 작성시 금물

    • 호출하는 쪽(Client)에서 알아서 잘 호출하겠지
      → 타입만 맞으면 어떤 값도 매개변수를 통해 넘어올 수 있기 때문에, 가능한 모든 경우의 수에 대해 고민하고 그에 대비한 코드를 작성
  • 예시) 나누기할 때 0으로 나눌 수 없기 때문에, 들어온 매개변수가 0인지 여부 체크

    • 유효하지 않으면 return 0;
  • 적절하지 않은 값이 매개변수를 통해 넘어온다면, 매개변수의 값을 보정하기

  • 보정하는게 불가능하다면 return문을 사용해서 작업을 중단하고 호출한 메서드로 돌아가기

  • [중요] 매개변수의 유효성 검사는 메서드의 작성에 있어서 간과하기 쉬운 중요한 부분



기본형 매개변수와 참조형 매개변수

  • 기본형 매개변수

    • 변수의 값을 읽기만 할 수 있음(read only)

    • 인자(argument) 값을 복사해서 매개변수(parameter)에 대입

  • 참조형 매개변수

    • 변수의 값을 읽고 변경할 수 있음(read & write)

    • 인자(argument) 주소를 복사해서 매개변수(parameter)에 대입

  • 참조형 매개변수를 활용하여 반환값이 없어도 메서드의 실행결과를 얻어올 수 있게하기

// 반환값 있음
int add(int a, int b) {
    return a + b;
}

// 반환값 없음
// result[]가 참조형 매개변수이기 때문에, 값을 가져감
void add(int a, int b, int[] result) {
    result[0] = a + b;
}



참조형 반환 타입

  • 반환타입도 참조형이 될 수 있음

  • 모든 참조형의 타입은 ‘객체의 주소’이므로 특별한 것은 없음

  • 메서드가 객체의 주소를 반환한다는 의미

  • 메모리에 값이 들어있고, 그 주소를 갖고있는 반환값을 새 변수에 대입하면, 새 변수가 그 주소를 갖게 됨

  • 메소드가 끝이나서 반환값 변수도 없어지지만, 새 변수가 해당 주소를 갖고있기 때문에 값이 있는 메모리에 접근할 수 있음



  • 메서드 내부에서 메서드 자신을 다시 호출하는 것

  • 재귀호출을 하는 메서드 : 재귀 메서드

  • 재귀 호출은 무한 반복되기 때문에, 조건문이 필수적으로 따라다님

  • 반복문으로 대체 가능

    • 반복문 : 그저 같은 문장을 반복해서 수행

    • 메서드 : 반복문보다 몇 가지 과정이 더 필요하기 때문에 반복문보다 수행시간이 더 오래걸림
      (예) 매개변수 복사, 종류 후 복귀할 주소 저장 등

  • 반복문 대신 재귀호출을 사용하는 이유

    • 재귀호출이 주는 논리적 간결함

    • 코드가 단순한 구조로 바뀜

  • 사용시 주의사항

    • 어떤 작업을 반복적으로 처리해야 한다면, 먼저 반복문으로 만들어보고 너무 복잡하면 재귀호출로 간단히 할 수 없는지 고민할 것

    • 단, 재귀호출은 비효율적이기 때문에 재귀호출에 드는 비용보다 재귀호출이 주는 간결함의 이득이 더 큰 경우에만 사용할 것

/* 재귀 호출 */
void method() {
    method(); // method 자기 자신을 호출함
}

/* 반복문과 비교 */
// 반복문
void method(int n) {
    while(n!=0) {
        System.out.println(n--);
    }
}
// 재귀호출메소드
void method(int n) {
    if(n==0)    return;
    
    System.out.println(n);
    method(--n);  // 재귀 호출
}



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

  • 클래스 메서드 : static이 메서드 앞에 붙어있음

    • 클래스변수처럼 객체를 생성하지 않고도 ‘클래스이름.메서드이름(매개변수)’와 같은 식으로 호출 가능
  • 인스턴스 메서드

    • 반드시 객체를 생성해야만 호출할 수 있음



클래스 메서드(static 메서드)와 인스턴스 메서드 : 참고사항

  • 클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에 static을 붙임

    • 생성된 각 인스턴스는 서로 독립적이기 때문에 각 인스턴스 변수는 서로 다른 값을 유지

    • 모든 인스턴스에서 같은 값이 유지되어야 하는 변수는 static을 붙여서 클래스 변수로 정의

  • 클래스 변수(static 변수)는 인스턴스를 생성하지 않아도 사용할 수 있음

    • static이 붙은 변수(클래스 변수)는 클래스가 메모리에 올라갈 때 이미 자동적으로 생성
  • 클래스 메서드(static 메서드)는 인스턴스 변수를 사용할 수 없음

    • 인스턴스변수는 인스턴스가 반드시 존재해야만 사용할 수 있음

    • 클래스메서드(static)는 인스턴스 생성없이 호출이 가능하므로 클래스 메서드가 호출되었을 때 인스턴스가 존재하지 않을 수도 있어서 인스턴스 변수 사용을 금지함

    • 인스턴스 변수나 인스턴스 메서드에서는 인스턴스 변수나 인스턴스 메서드가 존재한다면 static 변수가 이미 메모리에 존재하기 때문에 static이 붙은 멤버들을 사용할 수 있음

  • 메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려

    • 메서드의 작업내용 중 인스턴스 변수를 필요로 한다면, static을 붙일 수 없음

    • 메서드의 작업내용 중 인스턴스 변수를 필요로 하지 않는다면 static을 붙일 것

    • 메서드 호출시간이 짧아지므로 성능이 향상

    • 인스턴스 메서드는 실행시 호출되어야할 메서드를 찾는 과정이 추가적으로 필요하기 때문에 시간이 더 걸림



클래스 멤버와 인스턴스 멤버간의 참조와 호출

  • 멤버 : 변수 + 메서드

    • 클래스 멤버 : 클래스 변수 + 클래스 메서드

    • 인스턴스 멤버 : 인스턴스 변수 + 인스턴스 메서드

  • 같은 클래스에 속한 멤버들 간에는 별도의 인스턴스를 생성하지 않고 서로 참조 또는 호출이 가능

  • 단, 클래스 멤버가 인스턴스 멤버를 참조 또는 호출하려면 인스턴스를 생성해야 함

    • 인스턴스 멤버가 존재하는 시점에 클래스 멤버는 항상 존재(on Memory)

    • 클래스 멤버가 존재하는 시점에 인스턴스 멤버가 존재하지 않을 수 있기 떄문(on Memory)



알아두기

// 인스턴스 메서드 사용하기
// 1. 클래스타입 변수 생성 후 받기
Weather weather = new Weather();
String today = weather.today();

// 2. 바로 받기
// 단, 이럴경우 인스턴스를 다시 사용하진 못함(주소 저장을 안해서 - 1회용)
String today = new Weather().today();