본문 바로가기

Java

Java (메서드)

메서드는 특정 기능 또는 작업을 수행하기 위해 필요한 코드를 모아 놓은 것으로, 다른 부분에서 재사용할 수 있으며 여기에서 재사용 한다는 것이 자바에서 큰 의미를 갖게 되는데 이는 추후에 글을 올리도록 하겠다. 

 
한 마디로 정리하자면 메서드는 어떠한 기능들의 묶음이라고 먼저 생각하면 편하다. 

public class _01_Method {
    public static void sayHello() {
        System.out.println("안녕하세요 메소드입니다");
    }

    public static void main(String[] args) {
        System.out.println("메소드 호출 전");
        sayHello(); // 메소드 호출
        System.out.println("메소드 호출 후");
    }
}

 

Method라는 클래스에서 동작을 담당하는 메서드 즉 sayHello()가 메서드라고 볼 수 있다. 또한 메서드 명을 기입하는 것만으로도 메소드 호출이 가능토록 되어있다. 

 

메서드는 보시다시피 기능을 담당하기에 매개변수 즉 파라미터의 값이 주어지면 그 주어진 값으로 다양한 기능을 구현할 수 있기에 파라미터의 개념을 짚고 넘어가는 것이 중요하다.

public class _02_Paramiter {
    public static void power(int number) {
        int result = number * number;
        System.out.println(number + " 의 2승은 " + result);
    }

    public static void powerByExp(int number, int exponent) {
        int result = 1;
        for (int i = 0; i < exponent ; i++) {
            result *= number;
        }
        System.out.println(number + " 의" + exponent + " 승은 " + result);
    }

    public static void main(String[] args) {
        // 전달값
        power(2);
        powerByExp(2,4);
    }
}

 

Paramiter 라는 클래스안에 power, powerByExp 명칭을 가진 메서드를 지니고 있다. 각 각의 메서드는 이전의 코드와는 다르게 파라미터를 지니고 있는데, int 타입을 지닌 파라미터를 요구하고 있으며 이는 main 함수에서 메서드 호출 시, 요구하는 파라미터의 타입과 걸맞게 값을 전해주면 그 값에 따른 기능을 출력한다.

 

기능에 대해서 보자면 powerByExp는 값을 두 개를 받으며 number의 exponent 승의 값을 구하는 것으로, result에 1을 할당한 뒤 for 반복문을 활용하여   exponent 만큼 result = 1 의 값에 number만큼 곱하는 반복을 하여서 메서드의 기능을 구현하고 있다. 

 

여기서 각 메서드는 출력값을 println 화 하여서 반환하고 있지만 return이라는 것을 사용하여서 좀 더 쉽게 반환값을 정의내릴 수가 있다.

 

public class _03_Return {
    // 호텔 전화번호
    public static String getPhoneNumber() {
        String phonenumber = "02-1234-5678";
        return phonenumber;
    };

    // 호텔 주소
    public static String getAddress() {
        return "서울시 어딘가";
    }

    // 호텔 엑티비티
    public static String getActivities() {
        return "볼링장, 탁구장, 노래방";
    }


    public static void main(String[] args) {
        // 반환값 //void는 반환값이 없을 때만 쓴다
        String contactNumber = getPhoneNumber(); // return 값을 변수에 담음
        System.out.println("호텔 전화번호 : " + contactNumber);

        String address = getAddress(); // return 값을 변수에 담음
        System.out.println("호텔 주소 : " + address);

        System.out.println("호텔 엑티비티 : " + getActivities()); // 변수에 담지 않고 사용
    }
}

 

이번 코드에서는 각 메서드가 return값을 지니고 있다. 이는 메서드를 호출시 반환하는 값을 정의한 것, getPhoneNumber를 보게 된다면 String 타입의 변수를 정의한 뒤에 이를 return값에 적용시켜 반환값으로 정의내리고 있다.  

 

단순 print 하는 것과 return을 하는 것은 리턴 타입의 변화를 일으킨다. 이전의 코드를 본다면 메서드의 리턴 타입에 void가 있으며 return을 쓰는 메서드에서는 void가 없는 것을 알 수 있다 즉

 

void: 반환값이 없을 때 쓴다 (return이 없는 경우)

 

return을 쓰는 이유는 메서드의 결과 값을 다른 곳에서 유용하게 활용할 수 있어서이다. 반대로 말하면 그저 println으로 값을 출력하게 된다면 호출한 곳에서는 이 메서드를호출할 때 출력만 가능하고 다른 곳에서 이 결과를 다시 사용하거나 연산에 활용하기 어렵다. 하지만 return은 출력된 값을 변수에 저장하거나 다른 연산에 활용할 수가 있다.   

 

다음의 예시를 보자:

// print를 사용한 메서드
public void addAndPrint(int a, int b) {
    int result = a + b;
    System.out.println("두 수의 합은: " + result);
}

// return을 사용한 메서드
public int add(int a, int b) {
    int result = a + b;
    return result;
}
int sum = add(3, 5);
System.out.println("두 수의 합은: " + sum); // 결과: "두 수의 합은: 8"

 

위 코드를 통해서 void의 유무 차이를 알 수 있으며 return을 사용하면 print를 쓰는 것과는 다르게 반환된 값을 다른 변수에 저장 할 수 있다는 것과 다른 연산에 활용이 된다는 것을 알 수 있었다.

 

public class _04_ParamiterAndReturn {

    public static int getPower(int number) {
        int result = number * number;
        return result;
        // return number * number
    }

    public static int getPowerByExp(int number, int exponent) {
        int result = 1;
        for (int i = 0; i <exponent ; i++) {
            result *=number;
        }
        return result;
    };

    public static void main(String[] args) {
        // 전달값(파라미터)과 반환값이 있는 메소드
        int retVal = getPower(2); // 2 * 2 = 4;
        System.out.println(retVal);

        retVal = getPower(3);
        System.out.println(retVal); // 3 * 3 = 9

        retVal = getPowerByExp(5,5);
        System.out.println(retVal); //3125
    }
}

 

잠시 정리하는 시간으로 파라미터와 리턴 값을 동시에 쓰이는 코드를 보겠다. 각 메서드는 필요한 타입의 매개변수를 요구하고 있으며 return값을 반환 뒤, 변수에 저장하여 출력하는 것을 알 수 있다.  

 

소개에 메서드를 재사용하는 것이 자바에서 큰 의미를 갖는다라는 말을 하였었다. 사실 같은 기능을 하는 데, 파라미터의 수를 달리하고 싶거나 파라미터의 타입을 달리하고 싶을 때마다 메서드의 명칭을 각각 다르게 하여서 코딩을 하게 된다면 너무 비효율적이며 코드의 유지 보수가 어려워지게 된다.

 

즉 전달값의 타입을 달리 하고 싶거나, 전달값의 갯수가 달리하고 싶은 경우에는 메소드 오버로딩을 사용하면 된다. 이는 면접에서 물어보는 경우도 있으며 자바 코딩을 하면서 자주 사용하게 될 개념일 것이다. 예시 코드를 보여주겠다

 

public class _05_OverLoading {

    public static int getPower(int number) {
        int result = number * number;
        return result;
        // return number * number
    }

    public static int getPower(String strNumber) {
        int num = Integer.parseInt(strNumber);
        return num * num;
    };

    public static int getPower(int number, int exponent) {
        int result = 1;
        for (int i = 0; i <exponent ; i++) {
            result *=number;
        }
        return result;
    };
    public static void main(String[] args) {
        System.out.println(getPower(3)); // 9
        System.out.println(getPower("3")); //9
        System.out.println(getPower(3,3)); //27
    }
}

 

메소드 오버로딩을 알기 전에 메소드 시그니처 개념을 알고 가는 것이 더욱 이해하기 쉬울 것이다. 먼저 간단한 정의 먼저 알아보자면  메소드 시그니처는 메소드를 고유하게 식별하기 위한 정보로 다음과 같이 구성된다:

  • 메소드 이름
  • 매개변수 타입
  • 매개변수 개수

메소드 시그니처는 메소드를 고유하게 식별하여 오버로딩(Overloading)을 가능하게 하고. 같은 이름의 메소드라도 시그니처가 다르면 다른 메소드로 취급된다.

 

메소드 오버로딩: 

메소드 오버로딩은 같은 이름의 메소드를 여러 번 선언하는 것을 의미한다. 이때 메소드 시그니처가 다르게 구성되어 있어야 한다. 즉 메소드 오버로딩은 전달값의 타입을 다르게 하고 싶거나, 전달값의 갯수를 달리 하고 싶을 때 쓰이는 것으로 이해하는 것이 좋다.

 

위의 코드도 마찬가지로 메소드 이름은 같지만 파라미터의 타입과 갯수가 다르므로, 호출 시에 전달되는 인자에 따라 적절한 메소드가 선택되어 실행이 되도록하며 . 이를 통해 같은 이름의 메소드를 다양한 상황에서 사용할 수 있다.

 

public class _06_WhenToUse {
    public static int getPower(int number) {
        return getPower(number,2);
    };
    // 오버로딩을 이용하여 메소드 내에서도 또 다른 메소드를 호출 가능하다.

    public static int getPower(int number, int exponent) {
        int result = 1;
        for (int i = 0; i < exponent; i++) {
            result *= number;
        };
        return result;
    };

    public static void main(String[] args) {
        // 메소드가 필요한 이유

        // 메소드를 호출하여 1개의 값이 있으면 무조건 제곱하는 메소드를 구성
        
        System.out.println(getPower(3)); // 3 * 3 = 9

        // 2의 2승을 구하기
        System.out.println(getPower(2,2)); // 4

        // 3의 3승을 구하기
        System.out.println(getPower(3,3)); // 27

        // 4의 2승을 구하기
        System.out.println(getPower(4,2)); // 16
    }
}

 

getPower 메소드는 정수 하나를 받아서 해당 정수의 제곱 값을 반환한다. 이때, 두 번째 getPower 메소드는 두 개의 정수를 받아서 첫 번째 정수를 두 번째 정수만큼 제곱한 값을 반환힌다. 이처럼 두 메소드의 이름은 같지만 매개변수의 개수와 타입이 다르므로 오버로딩을 통해 구분된다.

 

여기서 중요한 점은메소드 내에서 다른 메소드 호출하는 것이 가능하다는 것으로. 이렇게 메소드 호출을 중첩하여 활용할 수 있다.

 

변수 범위

변수 범위란 자바 프로그래밍에서 변수는 선언된 위치에 따라서 사용할 수 있는 범위가 정해진다. 이를 "변수 범위"라 한다. 변수의 범위는 중괄호({})로 묶인 코드 블록 내에서만 사용할 수 있으며, 이외의 영역에서는 접근할 수 없다.

 

지역 변수:
지역 변수는 메서드 내부나 코드 블록 내에서 선언된 변수로, 선언된 중괄호({}) 내에서만 사용 가능합니다. 중괄호를 빠져나가면 해당 변수는 더 이상 접근할 수 없습니다. 아래의 예시를 살펴보겠습니다.

public static void main(String[] args) {
    int number = 3; // 메인 함수 중괄호 내에서 선언된 변수
    for (int i = 0; i < 5; i++) {
        System.out.println(i);
    }
    // System.out.println(i); // for문 내에서만 사용 가능한 변수
    {
        int j = 0;
        System.out.println(j);
        System.out.println(number); // 메인 함수 중괄호 내에서 선언된 변수 재사용
    }
    // System.out.println(j); // 중괄호를 벗어난 곳에서는 변수 j에 접근할 수 없음
}

 

주석을 보면 for 반복문안에서 정의된 int i 값은 반복문을 벗어나서는 쓰일 수 없다는 것을 알 수 있고 중괄호 내에서 정의된 int j 값도 중괄호를 벗어나면 쓰일 수 없다는 것을 알 수 있다.

 

전역 변수:
전역 변수는 클래스 내부에 선언되고 메서드 외부에서 사용 가능한 변수로, 해당 클래스 내의 모든 메서드에서 접근할 수 있습니다. 전역 변수는 클래스의 멤버 변수로 선언되며, 중괄호에 상관없이 사용 가능합니다. 

public class VariableScopeExample {
    // 전역 변수: 클래스 내부 어디서든 사용 가능
    private static int globalNumber = 10;

    public static void main(String[] args) {
        int localNumber = 5; // 지역 변수: 메서드 내부에서만 사용 가능
        System.out.println("지역 변수 localNumber: " + localNumber);
        System.out.println("전역 변수 globalNumber: " + globalNumber);
    }

    public static void anotherMethod() {
        // 여기에서도 전역 변수 globalNumber에 접근 가능
        System.out.println("다른 메서드에서의 전역 변수 globalNumber: " + globalNumber);
    }
}

 

 

변수 범위를 이해하면 메서드 내에서 변수를 선언하고, 해당 변수를 중괄호를 벗어나는 다른 영역에서 사용하거나 전역 변수를 클래스 내에서 활용할 수 있다. 이로써 변수의 재사용과 유연한 프로그래밍이 가능해진다.

 

마지막으로 메서드 오버로딩은 중요한 개념이니 꼭 알아두자:

 

메서드 오버로딩은 같은 이름의 메서드를 정의할 수 있는데 각 메서드가 지니는 파라미터의 타입이나 수를 달리하여 다양한 기능을 구현할 수 있도록 하는 것이다. 

'Java' 카테고리의 다른 글

Java (추상 클래스와 인터페이스, 의존성 주입)  (2) 2024.01.03
Java (클래스)  (2) 2024.01.02
Java (배열)  (1) 2023.12.31
Java (이중 반복문)  (0) 2023.12.31
Java (각 반복문 종류와 응용)  (0) 2023.12.31