inflearn

[인프런] 김영한의 자바 입문 강의 섹션9. 메서드 (240103)

hail2y 2024. 1. 3. 23:57

강의를 거의 다 들어놓고 마무리는 다음 날로 넘겨 버려서 할일이 연쇄적으로 밀리는 느낌이다ㅜㅜ

그래도 메서드를 끝으로 입문 강의는 이제 끝이니까 나름 후련하다!

이제 또 기본 강의를 향해 달려 나가야지! 아자아자!

1/3 섹션9 메서드 필기

  • 필요할 때마다 호출해서 사용 = 수학의 함수 => 자바에서는 메서드

지금은 또 그런가보다..~ 하고 익숙해 졌는데 처음에 인텔리제이에서 메서드 호출 부분을 보고 놀랐다.

왜냐면 int sum1= add(a:5, b:10);  메서드 호출하는데 인텔리제이에서는 앞에 매개변수를 살짝 써 준다. 처음에 이거 보고 자바에서는 함수 호출 이런 식으로 하나 생각했는데 강사님이 친절하게 이렇게 입력해서는 안된다고 일러 주셨다. 안 알려주셨으면 얄짤 없이 저렇게 썼을 판; 어쨌든 지금은 익숙해 졌다. 

 

처음 메서드 선언할 때 한 실수인데 메인 함수 안쪽이 아니라 바깥에 별도로 선언해 준다.

  • 메서드는 메인 함수 바깥에서 별도로 돌아가고 맨앞에 별도로 선언하지 않고 메인 함수 뒷편에 입력해도 별탈없이 동작한다.

cf. 메서드라는 말이 아직은 입에 안 붙어서 메인 함수, 함수 호출, 함수 선언... 이런 식으로 섞어 쓸 것 같다... 

 

  • 메서드는 메서드 선언, 메서드 본문으로 나눌 수 있다. 

엄청난 이론 내용 같지만 그냥 함수 머리, 본문이라 보면 된다- (또또..)

public static (반환형) 이름(매개변수) { -- 메서드 선언

--본문--

public static 덩어리로 외워둘 것!

  • 팁: 메서드 이름을 클릭하고 ctrl b 키를 누르면 해당 메서드로 이동한다.  

호출할 때 넘기는 값 = 인수, 인자, 아규먼트

정의할 때 선언한 변수 = 매개변수, 파라미터

--이제는 다 알 거라 생각했는데 여전히 헷갈리고 있는 중!^^;

  • 매개변수는 옵션이다. 입력 값이 필요없는 메서드는 매개변수를 지정하지 않아도 된다.
  • 반환 타입이 없는 경우는 void로 정의한다.
  • 반환 타입이 없으므로 메서드만 호출하고 반환 값을 받지 않으면 된다.
    즉, 반환 값이 있거나 반환 값을 받으면 컴파일 오류가 발생한다.  ex) String str = printHeader(); -- 오류 발생
  • 모든 메서드는 항상 return을 호출해야 한다. 다만 반환 타입이 void일 때는 예외로 생략해줄 수 있다.
    (자바 컴파일러가 자동으로 넣어준다.)
  • return을 쓰면 메인 메서드 바깥으로 나가 프로그램이 종료된다.

 

public static boolean odd(int i) {
    if (i % 2 == 1) 
        return true;
    }
}
  • 조건에 안 맞는 경우에 대해서도 return을 넣어주어야 한다. 들어오는 수가 짝수일 때 반환하지 않을 가능성이 있어 컴파일 오류를 낸다. 

반환 값을 일부러 안 받기도 한다. 그럴 때는 메서드를 수행만 한다. 예를 들어 add(100,200)을 호출했다고 하면 sum=300은 무시되고 메서드 내의 출력문만 실행된다. 

 

그리고 이건 c 할 때도 헷갈리던 거였고 이제는 이해되었다고 생각되는 지금에서도 헷갈리고 있던 거다(그냥 호기심을 이어붙이다보니 복잡하게 변해 있었다🤯) 위에 반환 값 없는 void 타입이랑 이어지는 내용인데 어떤 문자열만 출력하는 메서드는 따로 반환 값이 없으니 void 타입이겠지 출력만 하고(=작업만 수행하고) 끝이니까 근데 단순히 출력이 아니라 문자열을 반환해 출력한다고 생각해 버리면? 내가 이래서 c에서도 그냥 출력으로 하면 될 걸 return "문자열"로 써서 이게 뭐지를 많이 경험했었다...

 

1. 문자열만 단순히 출력하는 메서드라면 void로 선언하고 본문에 System.in.println("")을 쓴다. 

public static void printMessage(String message) { 
	System.out.println(message);
    // return;
}

 

 

 출력만 해 주니까 return 뒤에 문자열을 명시해 줄 필요도 없는 거지

 

2. 그 다음 가능/불가능의 관점으로 넘어가서 return이 어떤 걸 반환하는 애면 문자열도 반환할 수 있는지 보자. c는 문자열을 문자 배열로 저장해 놓고 쓰니까 자바보다도 더 복잡한 것 같다. 자바는 문자열부터 일단 간단히 선언할 수 있으니까-

public class Test1 {
    public static void main(String[] args) {
        String str = printMsg();
        System.out.println(str);
    }
    public static String printMsg() {
        return "문자열이 반환되었다!";
    }
}

 

 

그래서 반환 타입만 String으로 바꿔서 출력 가능한 걸 알 수 있었다. 근데 이렇게 쓰는 것보다 단순히 출력하는 게 더 편하겠지...! 그리고 다시 c로 넘어가서...

 

포인터 개념이 등장한다. 배열이다 보니 문자열 시작주소를 반환해 해당 문자열에 접근할 수 있도록 하는 방법을 사용한다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 문자열을 반환하는 함수
const char* getString() {
    const char* myString = "이 문자열을 반환합니다.";
    // 이 함수에서는 정적으로 할당된 문자열을 사용하고 있으므로 동적 할당 해제는 필요하지 않음
    return myString;
}

int main() {
    const char* returnedString = getString();
    printf("%s\n", returnedString);

    return 0;
}

 

위 코드는 chatGPT가 만들어 준 것인데, 반환 값을 문자열 포인터로 쓰고 포인터는 그 자체로 주소를 담고 있으니까 & 기호 없이 %s로 그대로 쓰게 되면 의도한 대로 결과가 나오는 것을 알 수 있다. 솔직히 여러 자료 찾아가며 const, static 다른 개념들 확실히 개념 세워두고 싶지만 지금 이거 쓰면서도 오래 걸렸고 좀 지쳐서 이 내용은 나중에 자바 강의에서나 따로 찾아봐서 확인해 보기로 한다...

 

그리고 강사님 피셜 아주아주아주 중요한 대원칙

- 자바는 항상 변수의 값을 복사해서 대입한다!

 

이 내용을 예제로 다뤄 보면서 딱히 어려웠던 건 없었지만 나중에라도 다시 헷갈릴 지도 모르니,

int num1 = 5;

int num2 = num1;  

=> num1에 들어있는 값을 읽고 복사해서 num2에 넣는다. 

이 코드가 뭘 의미하는지는 당연스럽게도 잘 알지만 값을 읽고 복사해서 대입한다는 것을 계속 들으니 도르마무처럼 어..? 하게 되는 것 같았다ㅋㅋㅋ 시각적으로 떠올리다보니 새롭다고 느꼈던 것 같지만 그래도 값을 복사해 대입한다는 건 기억하고 넘어가기! 참조형 변수도 똑같은데, 결국 참조형 변수에 있는 참조값을 복사해 사용한다. 

  • 메인 메서드와 일반 메서드에서 같은 변수명을 쓰더라도 각각 다른 메모리공간에 있는 다른 변수다.
  • 메서드를 호출할 때 매개변수에 인수를 전달하는 것도 결국 변수에 값을 대입하는 것과 같다.
  • 메서드 이름이 같아도 매개변수 정보로 구분할 수 있다. 
    메서드 오버로딩 = 이름이 같고 매개변수가 다른 메서드를 여러 개 정의하는 것

int add(int a, int b) 

double add(int a, int b)

위는 인정되지 않는다, 반환 타입이 달라도 메서드 이름, 매개변수 타입이 같으니 같이 쓸 수 없다.

  • 메서드 시그니처 = 메서드 이름 + 매개변수 타입(순서)  -- 메서드를 구분할 수 있는 기준

본인의 타입에 최대한 맞는 메서드 찾아 실행하고, 없으면 자동 형 변환 가능한 타입의 메서드를 찾아 실행한다.

 

좋은 코드란,

메인 함수만 보고 흐름 알 수 있는, 어떤 내용으로 흘러가는지 알 수 있는

 

목차처럼, 해당 목차 보고 이동하는 것처럼 읽히는 코드가 좋은 코드

 

메서드 추출: 기존에 쭉 있던 로직에서 구조적으로 필요한 부분만 똑 떼서 메서드로 뽑는 것

 

재사용하지 않더라도 프로그램(비즈니스 요구사항)을 구조적으로 읽기 좋게, 

세세한 구현은 메서드 안으로 숨겨도 stranger가 봐도 이해할 수 있게 메소드를 작성하는 게 중요하다!

 

  • 캡슐화 - 기능을 모아놓는다
  • 모듈성 - 관련있는 것끼리 묶어서 모듈처럼 만들어 놓는다
  • 추상화 - 메서드 사용하는 곳에서 메서드의 구현을 몰라도 된다
  • 테스트·디버깅 용이성 - 개별 메서드는 독립적으로 테스트하고 디버그 할 수 있다
  • 오버로딩 != 오버라이딩
    오버라이딩 = 메서드 자체를 새롭게 정의하는 것 (객체, 클래스에서 배울 수 있다.)

어쨌든 실무에서는 무조건 단순 명확하게 접근, 만들어야 한다!

너무 복잡한 케이스는 만들면 안 된다! 

 

정리하는 거에 시간을 너무 뺏겨서 새로운 진도를 아직 못 나갔다. 지금 밤 12시 다 돼 가는데...

'다음으로' 강의 가볍게 듣다가 기본 강의 얼른 들어봐야지~ PC룸에 사람들이 마구 떠들다 가서 오버로딩 이후부터 글을 어떻게 작성했는지 모르겠다. 하 또 남탓이지 짜증난 건 아니지만 그냥 혼자 있고 싶다 쓰읍.........😩

 

--끝--