6-4 메소드

Cloudman·2022년 11월 23일
0

항해99 자바 공부

목록 보기
5/10
post-custom-banner

★ 진행과정 ★

  • 클래스 (6 챕터)
    ◎ 스터디 그룹으로 진행
    ▷ 6-1 : 객체 지향 프로그래밍
    ▷ 6-2 : 필드
    ▷ 6-3 : 생성자
    ▶ 6-4 : 메소드
    ▷ 6-5 : 인스턴스 멤버와 정적 멤버
    ▷ 6-6 : 패키지와 접근 제한자



📒 메소드

객체의 동작에 해당하는 중괄호 {} 를 의미한다.
중괄호 블록의 이름이 메소드 이름이며 메소드를 호출하면 중괄호 블록에 있는 모든 코드들이 일괄적으로 실행된다.
메소드 선언은 선언부와 실행 블록으로 구성된다. 메소드 선언부를 메소드 시그니처 라고 한다.

  • 리턴 타입 : 메소드가 리턴하는 결과의 타입을 표시한다.
  • 메소드 이름 : 메소드의 기능이 드러나도록 식별자 규칙에 맞게 이름을 지어준다.
  • 매개 변수 선언 : 메소드를 실행할 때 필요한 데이터를 받기 위한 변수를 선언한다.
  • 메소드 실행 블록 : 실행할 코드를 작성



📋 메소드 선언

메소드 선언은 선언부(리턴 타입, 메소드 이름, 매개 변수 선언)와 실행 블록으로 구성된다.


🔖 리턴 타입

말 그대로 리턴값의 타입을 의미한다.
여기서 말하는 리턴값이란 메소드를 실행한 후의 결과값을 말한다.
리턴값이 있을 경우 리턴 타입이 선언부에 명시되어야 한다.(리턴값은 있을수도 없을수도 있다.)

▲ 전자 계산기를 예로...

powerOn() 메소드 : 전원만 키면 끝 그래서 리턴값이 없다. 리턴값이 없는 메소드는 리턴 타입에 void로 기입한다.
divide() 메소드 : 나눗셈의 결과를 리턴한다. 메소드의 결과가 double 타입이면 리턴 타입 또한 double 이다.

이를 직접 타이핑한다 치면 이러한 모습이다.

void powerOn() { ... }
double divide( int x, int y ) { ... }

리턴값이 있느냐 없느냐에 따라 메소드를 호출하는 방법이 다르다.
방금 두 메소드는 다음과 같이 호출할 수 있다.

powerOn();
// 리턴값이 없기 때문에 변수에 저장할 내용이 없다. 단순 호출로 끝

double result = divide( 10, 20 );
// 10 을 20 으로 나눈 후 0.5를 리턴, 리턴값을 받기 위해서 divide() 메소드의
   리턴 타입인 double로 선언되어야 한다.

리턴 타입이 있어도 리턴값이 중요하지 않고 메소드 실행이 목적일 경우에는 변수를 선언하지 않고 메소드의 호출 또한 가능하다.

divide( 10, 20 );




📋 메소드 이름

메소드 이름은 자바 식별자 규칙에 맞게 작성해야 한다.

  • 숫자로 시작하면 안되며, $ 와 _ 를 제외한 특수문자 사용 X
  • 관례적으로 메소드 이름은 소문자로 작성
  • 서로 다른 단어가 혼합된 이름은 뒤에 오는 단어의 첫글자만 대문자로

그렇다면 몇가지 예를 한번 만들어 보자

void run() { ... }
String getName() { ... }




📋 매개 변수 선언

매개 변수는 메소드가 실행할 때 필요한 데이터를 외부로부터 받기 위해 사용된다.
메소드에서 매개 변수가 필요한 경우가 있고 필요 없는 경우도 있다.

이에대한 예시가 앞서 보았던 예제에서도 있는데

아래의 코드가 바로 매개변수가 있는 divide() 메소드의 선언이다.
double divide( int x, int y ) { ... }

아래의 코드는 선언된 divide() 메소드를 호출할 때 2 개의 int 값을 주는 것이다.
double result = divide( 10, 20 );

이처럼 선언된 메소드에 맞게 매개값을(타입을) 정확하게 주지 않으면 컴파일 에러가 발생한다.

위 처럼 외부 클래스 Calculator 클래스의 메소드를 호출하기 위해서는
Calculator myCalc = new Calculator();
Calculator 객체를 생성하고 참조 변수인 myCalc(이름은 내 마음대로) 를 사용해야 한다.
myCalc 변수에 도트(.)와 함께 메소드이름(매개값) 형태로 호출하면 메소드 블록이 실행된다.




📋 매개 변수 개수를 모르면

보통은 메소드의 매개 변수는 개수가 정해져 있지만, 특정 상황에서는 메소드 선언 할 때 매개 변수의 개수를 알 수 없는 경우도 있다.
이에 대한 해결책으로는 매개 변수를 배열 타입으로 선언하는 것이다.

int sum1(int[] values) { ... }

sum1() 메소드를 호출할 때 배열을 넘겨줌으로써 배열의 항목 값들을 모두 전달할 수 있다.

int[] values = { 1, 2, 3 };
int result = sum1(values);
int result = sum1(new int[] { 1, 2, 3, 4, 5 });

매개 변수를 배열 타입으로 선언하면 메소드를 호출하기 전에 배열을 생성해야 하는 불편함이 존재한다.
그렇기에 배열을 생성하지 않고 값의 목록만 넘겨주는 방법도 있다.

int sum2(int ... values) { }

위처럼 메소드의 매개 변수를 ... 을 사용해서 선언하게 되면 메소드 호출 시 넘겨준 값의 수에 따라 자동으로 배열이 생성되고 매개값으로 상된다 !!!
... 로 선언된 매개 변수의 값은 아래처럼 메소드 호출 시 쉼표로 나열해주면 된다.

int result = sum2(1, 2, 3);
int result = sum2(1, 2, 3, 4, 5);

... 로 선언된 매개 변수는 배열 타입 그래서 배열을 직접 매개값으로 사용해도 된다.

이를 예시를 직접 해보면서 알아보자.

두 방식 모두 항목의 값을 모두 더해서 리턴해주는 것을 볼 수 있다.




📋 return 문


🔖 리턴값이 있는 메소드

메소드 선언에 리턴 타입이 있는 메소드는 반드시 리턴문을 사용해서 리턴값을 지정해야 한다.
없다면 컴파일 에러가 발생한다.

리턴문의 타입의 경우 리턴 타입이거나 리턴 타입으로 변환이 가능해야 한다.

위 예시를 보면 int 타입인 plus() 메소드에서는 byte, short, int 의 값이 리턴되어도 상관이 없다.
두 타입은 int 타입으로 자동 타입 변환되어 리턴되기 때문이다.



🔖 리턴값이 없는 메소드

이 경우에는 리턴 타입으로 void 를 사용한다.
다만, void 로 선언된 메소드에서도 return 문을 사용할 수 있다.
이 때에는 리턴값을 지정하는 것이 아니라 메소드 실행을 강제 종료시킨다.

위처럼 직접 쳐보면서 보면 훨씬 이해하기가 편하다.

위 과정을 좀 더 자세하게 풀이하면 아래와 같다.

myCar.setGas(5);
Car 객체의 setGas(5) 메소드를 호출해서 Car 객체의 gas 필드값을 5로 변경

boolean gasState = myCar.isLeftGas();
isLeftGas() 메소드를 호출해서 리턴값을 gasState 변수에 저장

if (gasState) {
    System.out.println("출발합니다.");
    myCar.run();    // Car 의 run() 메소드 호출
}

gasState 변수값이 true 일 경우 run() 메소드를 호출

if (myCar.isLeftGas()) {    // Car의 isLeftGas() 메소드 호출
    System.out.println("gas를 주입할 필요가 없습니다.");
} else {
    System.out.println("gas를 주입하세요.");
}

if 문의 조건식으로 isLeftGas() 메소드 호출이 들어가 있는데,
이것이 가능한 이유는 isLeftGas() 메소드가 boolean 값을 리턴하기 때문이다.
리턴값이 true 일 경우 if 블록을 실행, false 일 경우 else 블록을 실행한다.




📋 메소드 호출

메소드는 클래스 내, 외부의 호출에 의해 실행된다.
클래스 내부에서는 메소드 이름만으로 호출하고
외부에서는 클래스로부터 객체를 생성한 뒤 참조 변수를 이용해서 메소드를 호출한다.
이유는 객체가 존재해야 메소드도 존재하기 때문이다.


🔖 객체 내에서 호출

클래스 내부에서 다른 메소드를 호출할 경우에는다음과 같은 형태로 작성한다.
변수를 가지고 있을 때에는 매개 변수의 타입과 수에 맞게 매개값을 제공한다.

메소드 ( 매개값, ... );

method2() 메소드에서 method1() 메소드를 호출하려면 아래의 과정을 거친다.

  1. 호출에서 method1("홍길동", 100) 이 호출되면
    매개값인 "홍길동"p1 매개 변수에 대입되고
    100p2 매개 변수에 대입된다.
  2. 실행에서는 p1p2 변수를 이용한다.

리턴값이 있는 메소드를 호출하고 리턴값을 받고 싶다면 다음과 같이 변수를 선언하고 리턴값을 대입한다.

이 때, 변수 타입은 리턴 타입과 동일하거나, 자동 타입 변환이 될 수 있어야 한다.
예를 들어 intdouble 타입으로 자동 변환되기 때문에 int 리턴값은 double 타입 변수에 대입할 수 있습니다.



🔖 클래스 내부에서 메소드 호출

6 라인에서 Calculator 객체의 execute() 메소드를 호출하면 어떤 과정으로 실행되는지 살펴보겠습니다.




🔖 객체 외부에서 호출

외부 클래스에서 메소드를 호출하려면 우선 다음과 같이 클래스로부터 객체를 생성해야 한다.

클래스 참조변수 = new 클래스( 매개값, ... );

객체가 생성되었다면 참조 변수와 함께 도트(.) 연산자를 사용해서 메소드를 호출할 수 있다.
도트 (.) 연산자는 객체 접근 연산자로 객체가 가지고 있는 필드나 메소드에 접근할 때 사용된다.

다음의 코드를 예시로 설명하자면...

Car 객체의 KeyTurnOn() 메소드와 run() 메소드를 호출하는 코드이다.
KeyTurnOn()run() 메소드는 리턴값이 없기 때문에 단순 호출이다.
getSpeed() 메소드는 리턴값이 있으므로 리턴값을 받아 변수 speed 에 저장



이제 예제를 직접 만들어서 해보자 !!

위처럼 결과를 얻을 수 있다.




📋 메소드 오버로딩

클래스 내에 같은 이름의 메소드를 여러 개 선언하는 것을 말한다.
메소드 오버로딩의 조건은 매개 변수의 타입, 개수, 순서 중 하나가 달라야 한다.

이같은 행위가 필요한 이유는 매개값을 다양하게 받아 처리할 수 있도록 하기 위해서다.

만일 오버로딩된 메소드를 호출할 경우 JVM은 매개값의 타입을 보고 메소드를 선택한다.

아래의 예제로 설명을 하자면...

위처럼, plus1 메소드를 호출하면 매개값이 정수이므로 정상적으로 실행되어서 30 이라는 결과를 얻을 수 있다.

그리고 double 타입인 plus2 에도 저렇게 해주면 이번에는 소수이기 때문에 30.0 이라는 결과를 받을 수 있다.




🔗 핵심 정리

선언부 : 메소드 선언부는 리턴 타입, 메소드 이름, 매개 변수 선언 부분을 말한다.
void : 리턴값이 없는 메소드는 리턴 타입으로 void를 기입해야 한다.
매개 변수 : 메소드 호출 시 제공되는 매개값은 메소드 선언부의 매개 변수에 차례대로 대입되어, 메소드 블록 실행 시 이용된다.
리턴문 : 메소드 선언부에 리턴 타입이 있다면 리턴값을 지정하기 위해 return문이 반드시 있어야 한다.
리턴타입이 void 라면 리턴문은 필요 없지만, 메소드 실행 종료를 위해 사용될 수 있다.
호출 : 메소드를 실행하려면 '메소드 이름(매개값, ...)' 형태로 호출해야 한다.
오버 로딩 : 클래스 내에 같은 이름의 메소드를 여러 개 선언하는 행위를 말한다.
조건은 매개 변수의 타입, 개수, 순서 중 하나가 달라야 한다.

profile
코린이
post-custom-banner

0개의 댓글