메서드

황상익·2024년 3월 20일

Inflearn JAVA

목록 보기
11/61

메서드 시작

public class Method1 {
    public static void main(String[] args) {
        int a = 1;
        int b = 2;
        System.out.println(a + " + " + b);
        int sum1 = a + b;
        System.out.println("sum1 = " + sum1);

        int x = 10;
        int y = 20;
        System.out.println(x + " + " + y);
        int sum2 = x + y;
        System.out.println("sum2 = " + sum2);
    }
}

같은 연산을 두번 수행, 계산 부분이 거의 같다
계산1 , 계산2 둘다 변수를 두개 선언, 어떤 연산을 수행하는지 출력, 두 변수를 더해서 결과를 구한다.


함수 이름은 add
add(a, b) = a + b

같은 함수를 다른 입력값으로 여러번 호출 가능
핵심은 -> 한번 정의해놓으면, 재사용 할 수 있다.

메서드 사용

public class MethodRef1 {
    public static void main(String[] args) {
        int sum = add(1, 3);
        int sum2 = add(3, 4);
        System.out.println("sum = " + sum);
        System.out.println("sum2 = " + sum2);
        //메서드만 호출 하고 결과 안받고 사용 가능
        add(1, 2);
    }

    public static int add(int a, int b) {
        System.out.println(a + " + " + b + " = " + "연산수행");
        int sum = a + b;
        return sum;
    }
}

함수를 정의하는 것과 같이 메서드를 정의
메서드는 크게 메서드 선언과 본문으로 나눌 수 있다.

  1. 메서드 선언
    public static int add(int a, int b)
    메서드 이름, 반환 타입, 매개변수 목록을 포함

    - public static 

    public -> 다른 클래스에서 호출 가능 (접근제어자)
    stataic -> 객체를 생성하지 않고 호출 할 수 있는 정적 메서드

    -int add (int a, int b)
    int -> 반환타입을 정의
    add -> 메서드에 이름을 부여
    (int a, int b) -> 메서드를 호출할때 전달하는 입력 값을 정의

  2. 메서드 본문

{
 System.out.println(a + "+" + b + " 연산 수행");
 int sum = a + b;
 return sum;
}

메서드가 수행하는 코드 블록
메서드를 호출하면, 메서드 본문이 순서대로 호출
메서드를 호출하는 곳에서 메서드 선언은 알지만, 메서드 본문은 모름
메서드 실행 결과를 반환 하려면 return 사용

메서드 호출이 끝나면 메모리에서 제거

메소드 호출과 용어정리

메서드를 호출할 "때 메서드에 넘기는 값과 매개변수 타입이 맞아야 한다 .
물론 넘기는 값과 매개변수의 순서와 개수도 맞아야 한다.

인수
넘기는 값을 영어로 argument, 한글로 인수

매개변수
메서드를 정의할때 변수인 String str, int age 매개변수 (파라미터)
호출할떄 인수를 넘기면, 인수가 매개변수에 대입

메서드 정의

public static int add(int a, int b) {
 //메서드 본문, 실행 코드
}
제어자 반환타입 메서드이름(매개변수 목록) {
 메서드 본문
}

제어자 -> public, static 같은 부분

반환 타입 -> 메서드가 실행 된 후 반환하는 데이터의 타입을 지정. 메서드가 값을 반환 하지 않는 경우 void

메서드 이름 -> 메서드 호출용

매개변수 -> 메서드 내부에서 사용할 수 있는 변수, 매개변수는 옵션. 입력값 필요헚는 메서드는 매개변수를 지정하지 않아도 된다.

메서드 본문 -> 실제 메서드의 코드가 위치

매개변수 X or 반환 타입이 없는 경우

public class Method2 {
    public static void main(String[] args) {
        printHeader();
        printFooter();
    }

    public static void printHeader(){
        System.out.println("Program start");
    }

    public static void printFooter(){
        System.out.println("Byebye");
    }
}

매개변수 X
선언 : public static void printHeader() 매개변수를 비워놓고 정의
호출 : printHeader(); 인수를 비워서 호출

반환 타입X
선언 : public static void printHeader() -> void 호출
호출 : 메서드만 호출하고 반환 값을 받지 않으면 ok

void 와 return 생략
모든 메서드는 항상 return 호출, 그런데 반환타입 void의 경우 return X

반환 타입
반환 타입이 있다면 return 사용

public class MethodReturn1 {
    public static void main(String[] args) {
        boolean rst = odd(2);
        System.out.println(rst);
    }

    public static boolean odd(int a){
        if (a % 2 == 1){
            return true;
        }
        return false;
    }
}

return문을 만나면 즉시 메서드를 빠져나간다.

public class MethodReturn2 {
    public static void main(String[] args) {
        checkAge(18);
        checkAge(10);
    }

    public static void checkAge(int age){
        if (age >= 18){
            System.out.println("출입 가능");
        } else {
            System.out.println("출입 불가능");
        }
    }
}

반환 값 무시
반환 타입이 있는 메서드를 호출, if 반환 값이 없다면 사용 하지 않다도 된다.

메서드 호출과 값 전다
자바는 항상 변수의 값을 복사해서 대입한다 (중요!!!!!!!!)

public class MethodValue0 {
    public static void main(String[] args) {
        int num1 = 5;
        int num2 = num1;
        num2 = 10;

        System.out.println("num1 = " + num1);
        System.out.println("num2 = " + num2);
    }
}
int num2 = num1; //num1의 값은 5이다. num1(5)
int num2 = 5; //num2 변수에 대입하기 전에 num1의 값 5를 읽는다. 결과: num1(5), num2(5)
num2 = 10; // num2에 10을 대입한다. 결과: num1(5), num2(10)

값을 복사해서 대입한다는 부분은
-> int num2 = num1;
num1에 값을 복사해서 num2에 넣는 것이다
복사한다고 표현하는 이유는 num1의 값을 읽어도 num1의 값은 유지, num2에 새로운 값이 들어가기 때문.
num1 이라는 변수 자체가 num2에 들어가는 것이 아니다. num1에 들어 있는 값을 읽고 복사해서 num2에 넣는 것

메서드 호출과 값 복사

public class MethodValue1 {
    public static void main(String[] args) {
        int num1 = 5;
        System.out.println("1 호출 전 num1 :" + num1);
        changeNumber(num1);
        System.out.println("4 호출 후 num1 :" + num1);

    }

    public static void changeNumber(int num2){
        System.out.println("2 변경 전 num2: " + num2);
        num2 = num2 * 2;
        System.out.println("3 변경 후 num2:" + num2);
    }
}

결과적으로 매개변수 num2의 값만 10으로 변경되고, num1에는 영향을 주지 않는다.

메서드 호출과 값 전달 2

public class MethodValue2 {
    public static void main(String[] args) {
        int number = 5;
        System.out.println("1 호출 전 num1 :" + number);
        changeNumber(number);
        System.out.println("4 호출 후 num1 :" + number);

    }

    public static void changeNumber(int number) {
        System.out.println("2 변경 전 number: " + number);
        number = number * 2;
        System.out.println("3 변경 후 number:" + number);
    }
}

main()도 사실은 메서드이다. 각각 메서드 안에서 사용하는 변수는 서로 완전히 분리된 다른 변수

실행 과정 
changeNumber(number); //changeNumber를 호출한다. main의number(5)
changeNumber(5); //number의 값을 읽는다.
//main의 number값 5가 changeNumber의 number에 복사된다.
//결과: main의 number(5), changeNumber의 number(5)
void changeNumber(int number=5) 
//changeNumber의 number에 값 10을 대입한다.
//결과: main의 number(5), changeNumber의 number(10)
number = number * 2;
main의 number을 출력한다: main의 number의 값인 5가 출력된다.

메서드 호출과 값 반환받기

public class MethodValue3 {
    public static void main(String[] args) {
        int num1 = 5;
        System.out.println("1 호출 전 num1 :" + num1);
        num1 = changeNumber(num1);
        System.out.println("2 호출 후  num1 :" + num1);

    }

    public static int changeNumber(int num2) {
        num2 = num2 * 2;
        return num2;
    }
}

정리
자바는 항상 변수의 값을 복사해서 대입, 후에 정리할 참조형 변수도 마찮가지 이다.

메서드와 형 변환
메서드르 호출할때도 형 변환이 적용 . 메서드 호출과 명시적 형 변환, 자동 형 변환

명시적 형변환
메서드를 호출하는데 인자와 매개변수의 타입이 맞지 않는다면?

public class MethodCasting1 {
    public static void main(String[] args) {
        double number = 1.5;
        //printNumber(number); -> double을 int형 대입함으로 컴파일 오류
        printNumber((int) number); //명시적 형 변환
    }

    public static void printNumber(int a){
        System.out.println("숫자 :" + a);
    }
}

결과
-> 컴파일 오류
printNumber(number) -> 1.5 실수
printNumber(1.5) -> 메서드를 호출하기 전에 number 변수의 값을 읽는다
void printNumber(int n=1.5) -> int형 매개변수 n에 double형 실수 대입 시도
= 결과 (CompileError)

이 경우 메서드 호출리 필요하다면 명시적 형변환 필요

printNumber((int) number); // 명시적 형변환을 사용해 double을 int로 변환
printNumber(1); // (double) 1.5 -> (int) 1로 변환
void printNumber(int n=1) //int형 파라미터 변수 n에 int형 1을 대입

자동형변환
int < long < double

public class MethodCasting2 {
    public static void main(String[] args) {
        int number = 100;
        printNumber(number);
    }

    public static void printNumber(double a){
        System.out.println("숫자 : " + a);
    }
}

이경우 자동형 변환 발생

메서드 오버로딩

이름이 같고 매개변수가 다른 메서드를 여러개 정의 하는 것을 메서드 오버로딩
오버로딩을 번역하면 과적, 과하게 물건을 담았다는 의미.

오버로딩 규칙
메서드의 이름이 같아도 매개변수의 타입 및 순서가 다르면 오버로딩을 할 수 있다.

오버로딩 성공 
add(int a, int b)
add(int a, int b, int c)
add(double a, double b)

오버로딩 실패 `
int add(int a, int b)
double add(int a, int b)

메서드 시그니처
메서드 시그니처 = 메서드 이름 + 매개변수 타입
메서드 시그니처는 자바에서 메서드를 구분할 수 있는 고유한 식별자나 서명을 의미
시그니처 메서드의 이름과 매개변수 타입으로 구성.
자바 입장에서는 각각의 메서드를 고우하게 구분.
메서드 이름이 같아도 시그니처가 다르면 다른 메서드로 간주

  1. 매개변수의 갯수가 다른 오버로딩
public class Overloading1 {
    public static void main(String[] args) {
        System.out.println("1 :" + add(1, 2));
        System.out.println("2 :" + add(1, 2, 3));
    }

    public static int add(int a, int b) {
        System.out.println("1번 호출");
        return a + b;
    }

    public static int add(int a, int b, int c) {
        System.out.println("2번 호출");
        return a + b + c;
    }
}
  1. 매개변수의 타입이 다른 오버로딩
public class Overloading2 {
    public static void main(String[] args) {
        myMethod(1, 2.0);
        myMethod(2.0, 1);
    }

    public static void myMethod(int a, double d){
        System.out.println("int a , double d");
    }

    public static void myMethod(double a, int d){
        System.out.println("double a , int d");

    }
}
  1. 매개변수 타입이 다른 경우
public class Overloading3 {
    public static void main(String[] args) {
        System.out.println("1 : " + add(1,2));
        System.out.println("2 : " + add(1.0,2.0));
    }

    public static int add(int a, int b){
        System.out.println("1번 호출");
        return a + b;
    }

    public static double add(double a, double b){
        System.out.println("2번 호출");
        return a + b;
    }
}

연습문제

public class Practice1 {
    public static void main(String[] args) {
        avg(1,2,3);
        avg(15,25,35);
    }

    public static double avg(int a, int b, int c){
        int sum = a + b + c;
        double average = sum / 3.0;
        System.out.println("평균 값 : " + average);
        return average;
    }
}
public class Practice2 {
    public static void main(String[] args) {
        hello("Hello World", 3);
        hello("Hello World", 5);
        hello("Hello World", 7);
    }

    public static void hello(String str, int times){
        for (int i = 0; i < times; i++) {
            System.out.println(str);
        }
    }
}
public class Practice3 {
    public static void main(String[] args) {
        System.out.println(depositAmount(10000, 5000));
        System.out.println(withdrawAmount(10000, 5000));
        System.out.println(withdrawAmount(10000, 20000));
    }

    public static int depositAmount(int balance, int money){
        balance += money;
        return balance;
    }

    public static int withdrawAmount(int balance, int money){
        if (balance < money){
            return 0;
        }

        return balance - money;
    }
}
public class Practice1 {
    public static void main(String[] args) {
        int balance = 0;
        System.out.println("1.입금 | 2.출금 | 3.잔액 확인 | 4.종료");
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt();
        int amount;

        switch (a) {
            case 1:
                System.out.println("입금액을 입력하세요");
                amount = sc.nextInt();
                balance = add(balance, amount);
                break;

            case 2:
                System.out.println("출금액을 입력하세요");
                amount = sc.nextInt();
                balance = withdraw(balance, amount);
                break;

            case 3:
                System.out.println("현 잔액 통장");
                balance = getBalance(balance);
                break;

            case 4:
                System.out.println("프로그램을 종료합니다");
                break;

            default:
                System.out.println("잘 못 입력하셨습니다");
                break;
        }
    }

    public static int add(int balance, int money) {
        balance += money;
        System.out.println(money + "원을 입금하셨습니다. 현재 잔액 : " + balance);
        return balance;
    }

    public static int withdraw(int balance, int money) {
        if (balance < money) {
            return 0;
        }
        System.out.println(money + "원을 출금하셨습니다. 현재 잔액 : " + balance);
        return balance - money;
    }

    public static int getBalance(int balance) {
        System.out.println("현재 잔액 : " + balance);
        return balance;
    }
}
profile
개발자를 향해 가는 중입니다~! 항상 겸손

0개의 댓글