본문 바로가기

Java/Chapter 06. 메소드와 변수의 스코프

[Java] 06.01 - 메소드에 대한 이해와 메소드의 정의

들어가며

 지금까지 예제를 작성할
때마다

 main이라는 이름의 메소드
내에 실행할 내용을 담아
두었다.

 이러한 main 메소드의 실행
원리만 이해하더라도

 메소드의 기본 성질을 파악할
수 있다.

 따라서 main에 대한 관찰에서
부터 이야기를 시작하고자 한다.

 

main 메소드에 대해서 우리가 아는것과 모르는 것

 앞서 main이 메소드이고,
이 메소드는

 클래스의 내부에 존재해야
함을 간단히 보였다.

 따라서 다음 메소드를 보면서
우리가 아는 것과 모르는 것들을
정리해 보겠다.

public class temp {
    public static void main(String[] args) {
        int num1 = 5;
        int num2 = 7;
        System.out.println("5 + 7 = " + (num1+num2));
    }
}

 아는 것은 다음 두 가지
정도로 정리가 된다.

  • 메소드의 이름은 main이다.
  • 메소드의 중괄호 내에 존재하는 문장들이 위에서 아래로, 순차적으로 실행된다.

 모르는 것들은 다음과 같다.

  • public, static 그리고 void가 왜 붙어있고 의미하는 바가 무엇인가?
  • 이름은 왜 항상 main이어야 하는가?
  • 메소드의 이름 오른편에 있는 소괄호와 그 안에 위치한 'String[] args'는 무엇인가?

 이번 Chapter에서도 public에
대해서는 설명하지 않는다.

 이들에 대해서는 적절한 시기에
설명을 할 테니

 당분간은 '그냥 붙여줘야 하는
키워드' 정도로 기억하자.

 

 

다른 이름의 메소드 제작

 지금까지 만들어온 메소드의
이름이 항상 main인 이유는

 다음 약속에 근거한다.

 즉, main이라고 이름을 붙이는
이유는 일종의 약속이다.

자바 프로그램은 main이라는 이름의
메소드에서부터 시작을 한다.

 따라서 추가로 만들게 될
(정의하게 될) 메소드의 이름은

 다음과 같이 직접 결정하면
된다.

public static void damageText(double damage) {
    System.out.println(damage + "의 피해를 입혔습니다.");
}

 위의 코드 내용을 가리켜
'메소드의 정의'라고 한다.

 즉 위의 코드는 '메소드
damageText의 정의'이다.

 그럼 메소드 damageText의
오른편에 위치한 소괄호를
보자.

 이곳에 변수 damage의 선언이
위치해 있다.

 이 변수가 언제 어떻게 활용
되는지 다음 예제를 통해
확인해보자.

 더불어 위에 정의된 메소드를
어떻게 실행(호출)하는지
확인하자.

public class temp {
    public static void main(String[] args) {
        System.out.println("공격 시작");
        damageText(12.34);
        damageText(15.64);
        System.out.println("공격 끝");


    }
    public static void damageText(double damage) {
        System.out.println(damage + "의 피해를 입혔습니다.");
    }
}
/*
실행 결과
공격 시작
12.34의 피해를 입혔습니다.
15.64의 피해를 입혔습니다.
공격 끝
*/

 위 예제에 다음 문장이
존재한다.

 이것이 메소드 damageText의
실행을 명령하는 문장이다.

 이렇듯 메소드의 실행을
명령하는 문장을 가리켜

 '메소드의 호출문'이라 한다.

damageText(12.34);    // 메소드 damageText를 호출하는 문장
damageText(15.64);

 위 문장에서 보면 소괄호
안에 실수를 넣었는데,

 이는 메소드 damageText에
전달할 값을 표시한 것이다.

 즉 실수 12.34와 15.64를
전달하면서

 메소드의 호출을 명령하는
것이다.

그림 48 - 메소드의 호출과 값의 전달

 위 그림에서 보이듯이

 메소드를 호출할 때 전달한
숫자 12.34와 15.64는

 damageText의 오른편 소괄호에
선언된 변수 damage에 전달된다.

 이렇듯 메소드 호출 시 전달되는
값을 받기 위해 선언된 변수를

 '매개변수'라 하며, 이러한 변수는
다음의 특징을 가진다.

  • 메소드 호출 시 선언되어, 전달되는 값을 저장한다.
  • 매개변수가 선언된 메소드 내에서만 유효한 변수이다.

 그리고 예제에서 보이듯이,

 정의된 메소드는 여러 번
호출이 가능하며

 메소드의 정의 위치는

 프로그램에 영향을 미치지
않는다.

 즉, main 메소드가 damageText
메소드보다 먼저 등장하건 나중에
등장하건

 아무 사이가 없다.

 그럼 예제를 하나 더 제시
하겠다.

 이번에는 매개변수가 2개인
메소드를,

 그리고 매개변수가 존재하지
않는 메소드를 정의해 보겠다.

public class temp {
    public static void main(String[] args) {
        System.out.println("공격 시작");
        damageText(12.34, false);
        damageText(15.64, true);
        enemySlainText();
        System.out.println("공격 끝");
    }
    
    public static void damageText(double damage, boolean critical) {
        if (critical == true)
            System.out.println(((1.5)*damage) + "의 치명타 피해를 입혔습니다.");
        else
            System.out.println(damage + "의 피해를 입혔습니다.");
    }
    
    public static void enemySlainText(){
        System.out.println("적을 처치하였습니다.");
    }
}
/*
공격 시작
12.34의 피해를 입혔습니다.
23.46의 치명타 피해를 입혔습니다.
적을 처치하였습니다.
공격 끝
*/

 위 예제에 정의된 다음
메소드를 보자.

 이 메소드 정의는 매개변수의
선언이 둘 이상이 될 수 있음을
보인다.

public static void damageText(double damage, boolean critical) { . . . }

 물론 위 메소드를 호출할
때에는

 다음과 같이 매개변수의 수와
자료형이 일치하는 값을
전달해야 한다.

damageText(12.34, false);
damageText(15.64, true);

 그리고 다음과 같이 값의
전달이 불필요한 경우에는

 메소드의 매개변수 선언을
생략할 수 있다.

public static void enemySlainText(){ . . . }

 물론 위 메소드를 호출할
때에는

 다음과 같이 전달하는 값이
없어야 한다.

enemySlainText();

 

값을 반환하는 메소드

 지금까지 메소드 호출 시
값을 전달할 수 있음을
보였다.

 그러나 반대로, 메소드 내에서
메소드를 호출한 영역으로

 값을 전달할 수도 있다.

 그리고 이러한 상황을 가리켜
'값의 반환'이라고 하는데,

 다음 예제를 통해서 이 상황을
보이겠다.

public class temp {
    public static void main(String[] args) {
        int damage;
        damage = doubleAttack(12, 15);
        System.out.println(damage + "의 피해를 주었습니다.");
        System.out.println(tripleAttack(11) + "의 피해를 받았습니다.");

    }

    public static int doubleAttack(int damage1, int damage2) {
       int final_damage = damage1 + damage2;
       return final_damage;
    }

    public static int tripleAttack(int damage){
        return (damage * 3);  // gold * 2의 결과를 반환
    }
}
/*
27의 피해를 주었습니다.
33의 피해를 받았습니다.
*/

 먼저 main 메소드를 보자.

 main이라는 이름 왼편에는
void라는 키워드가 존재한다.

 이는 다음의 의미를 지닌다.

void
이 메소드는 값을 반환하지 않을테니,

그런 줄 아쇼

 이렇듯 메소드의 이름 왼편에는
'메소드가 반환하는 값의 자료형
정보'를 삽입하게 되어 있다.

 그리고 우리가 지금까지 정의한
메소드들은

 값을 반환하지 않았기 때문에
이곳에 항상 void가 위치하였다.

 이번에는 예제의 doubleAttack과
tripleAttack을 보자.

 메소드의 이름 왼편에 각각
int와 double이 위치하고
있는데,

 이들 각각이 의미하는 바는
다음과 같다.

doubleAttack 메소드는 int형 값을 반환한다.
tripleAttack 메소드는 double형 값을 반환한다.

 그렇다면 값의 반환을 명령하는
문장은 어떻게 구성하는가?

 이에 대한 이해를 위해서
doubleAttack 메소드를

 조금 더 자세히 관찰해 보겠다.

그림 49 - 값의 반환과 return문

 위 그림에서는 doubleAttack
메소드의 두 군데를 강조하고
있다.

 하나는 메소드의 이름 왼편에
존재하는 반환형이고,

 다른 하나는 메소드 내에 존재
하는 return이라는 키워드이다.

 그런데 이 return은 값의 반환을
명령하는 키워드이다.

 즉 그림의 return문이 갖는
의미는 다음과 같다.

final_damage에 저장된 값을 반환하셈 ㅇㅇ

 이렇듯 return은, 그 오른쪽에
등장하는 값을 반환하는데,

 이곳에는 값뿐만 아니라,

 예제에서 보이듯이 연산이
올 수도 있으며,

 이러한 경우에는 연산이
진행되어 그 결과를 반환
하게 된다.

 메소드 호출 이후에 값이
반환되어 다음과 같은 문장
구성을 이루게 된다.

damage = 27;
// = damage = doubleAttack(12, 15);
System.out.println(33 + "의 피해를 받았습니다.");
// = System.out.println(tripleAttack(11) + "의 피해를 받았습니다.");

 

키워드 return이 지니는 2가지 의미

 return문이 실행되면 메소드가
종료되면서 값이 반환된다.

 즉 키워드 return이 갖는 의미
2가지는 다음과 같다.

  • 메소드를 호출한 영역으로 값을 반환
  • 메소드의 종료

 따라서 메소드 중간에 return문이
실행되면

 값이 반환되면서 메소드의
실행은 종료가 된다.

 그리고 다음 예제에서 보이듯이

 반환형이 void로 선언된
메소드 내에서도

 값의 반환이 아닌 메소드의
종료를 목적으로 return문을
사용할 수 있다.

public class temp {
    public static void main(String[] args) {
        attack(10, 9);
        attack(7, 14);
        attack(0, 0);

    }

    public static void attack(int damage1, int damage2) {
        if ((damage1 == 0) && (damage2 == 0)){
            System.out.println("공격에 실패하였습니다.");
            return;
        }
        System.out.println((damage1 + damage2) + "의 피해를 입혔습니다.");
        return;
    }
}
/*
19의 피해를 입혔습니다.
21의 피해를 입혔습니다.
공격에 실패하였습니다.
*/

참고 및 출처

윤성우의 열혈 Java 프로그래밍
국내도서
저자 : 윤성우
출판 : 오렌지미디어 2017.07.05
상세보기