Java

[Java] 05. 메소드와 파라미터*

Joo.v7 2024. 8. 23. 22:08

Chatper 1: 메소드

  • 메소드 선언
  • 메소드 호출
  • return statement
  • 지역 변수
  • 값 return

Chapter 2: 파라미터(Parameter)

  • 파라미터 선언과 호출
  • 파라미터 전달 매커니즘
  • Pass by Value, Pass by Reference
  • 가변 길이 목록 파라미터 사용
  • 재귀 메소드 사용

Chapter 3: 메소드 오버로딩(Method Overloading)

  • 메소드 오버로딩 정의
  • 메소드 시그니처
  • 오버로드된 메소드 사용

Lab 5-2 메소드 오버로딩


Chatper 1: 메소드

 Function(함수): 특정 값을 넣으면 반드시 계산 결과의 값을 반환

 Procedure(프로시저): 값을 반환하지 않고 절차만을 수행.

(C 이후의 언어들은 2가지의 경계가 모호해져서 return이 있어야 함수인데 void를 사용해서 반환값이 없어도 된다)

 

 Method(메소드):  Java에서 함수를 사용하려면, 클래스 아래에 선언된 함수를 해당 클래스의 객체를 생성해서 사용해야 한다. 이 동작(행위)를 method라고 한다. 따라서 객체지향언어에서 메소드는 함수와 프로시저의 총칭이다.

 

* 객체지향 언어: 객체를 만들어서 객체 간 상호작용을 통해 문제를 해결하고 값을 산출하는 언어이다.

 

Static binding(정적 바인딩): 컴파일 시점에 호출이 결정. (실행 이전에 값이 확정)

Dynamic binding(동적 바인딩): 런타임 시점에 호출이 결정. (실행 이후에 값이 확정)

 

메소드 선언

  • 메소드
    • 특정 작업을 수행하는 일련의 문장들을 하나로 묶은 것.
    • 함수, 서브루틴, 프로시저, 서브 프로그램과 비슷한 개념.
  • main 메소드: Java 응용 프로그램의 진입점(Application Entry Point)
  • 메소드 형식
    • public [static] int MethodName() { }
    • public: Access Modifier, [static]: Binding Type, int: Return_type
public class MyClass {
	static void myMethod() {
    	System.out.println("Example method");
    }
    public static void main(String[] args) {
        System.out.println("main method");
    }
}

 

메소드 호출

  • 같은 클래스 내에서 메소드 호출. ex) myMethod();
  • 다른 클래스에 있는 메소드 호출. ex) OtherClassName.methodInOtherClass();
  • 중첩 호출: 메소드 내에서 메소드를 호출할 수 있다.
public class Sample {

    public static int add(int i, int j) {
        return i+j;
    }
    
    public static void main(String[] args) {
    
        add(1,2); // add는 static이기 때문에 이렇게 사용이 가능하다
        // 만약 add라는 static이 Sample2에도 같이 선언되어 있다면, 
        // 같은 클래스 내에 있는 add 메소드를 호출한다.
        
        // dynamic 메서드(static)을 안쓰면 이렇게 호출해야함
        // Sample s = new Sample();
        // s.add(1,2);
    }
}

class Sample2 { 
    private static int add(int i, int j) {
        return Sample.add(i, Sample.add(1,2)); 
        // 호출자 입장에서는 메소드는 return 타입으로 보인다 add는 int로 보임
    }
}

 

return statement

  • return: "귀환", "반환".
  • return문을 만나면 메소드는 즉시 종료된다. 
  • 조건문에서 return 할 수 있다. (그냥 쓰면 unreachable statement 오류가 발생하기 때문이다)
  • 메소드 종료: return / 메소드 내 모든 statement가 실행.
/* i가 10보다 작을 경우 즉시 return */
static void method1() {
    int i = 10;
    System.out.println("Hello");
    if (i < 10)
        return;
    System.out.println("World!");
}

 

실행결과

/* i<10 경우 */
Hello

/* i>=10 경우 */
Hello
World!

 

지역 변수 (Local Variable)

  • 메소드가 시작할 때 생성.
  • 메소드 내에서만 유효.
  • 메소드 종료시(return / 모든 statement 실행) 제거.

전역 변수 (클래스 내 공유 변수)

  • 클래스 레벨에서 선언된 변수로 클래스 내 모든 메소드에서 공유된다.
/* 공유 변수 count */
public class MethodCall {
    static int count = 0;

    static void myMethod() {
        ++count;
        System.out.printf("메소드가 %d 번 호출되었습니다.\n", count);
    }

    public static void main(String[] args) {
        myMethod();
        myMethod();
    }
}

 

값 return

  • return type이 void인 메소드: 값을 반환하지 않는다. ex) return;
  • return type이 void가 아닌 메소드: return type을 반환한다. ex) return sum;
  • Call Stack (콜 스택): 프로그램 실행 중에 함수(메소드)의 호출을 추적하고 관리하는 메모리 구조.
public class test {
    static int add(int i, int j) {
    	int sum;
        sum = i+j;
        
        return sum; 
    }

    public static void main(String[] args) {
        add(1,2);
    }
}

 

 


Chapter 2: 파라미터

 메소드 정의 ex) methodName(int i, int j) : format parameter / parameter 라 부른다.

 메소드 실행 ex) methodName(1, 2): actual parameter / argument 라 부른다.

 

파라미터 선언과 호출

  • 파라미터를 사용하면 정보를 메소드 안으로 전달하고 밖으로 반환할 수 있다.
  • 파라미터 선언: 메소드 이름 뒤 괄호( )에 선언.
  • 파라미터에 argument 전달: 메소드를 호출하여 파라미터에 argument를 전달. (Type이 같아야함) 
static void defineParametersIntoMethod(int n, string s) {
    ...
}
defineParametersIntoMethod(1, “Hello, World!”)

 

파라미터 전달 매커니즘

  • Pass by Value
    • 값을 복사해서 전달.
    • 값을 수정해도 원본 데이터에는 영향을 미치지 않음.
  • Pass by Reference
    • 주소 값을 전달 - 실제 값이 있는 위치를 전달.
    • 값을 수정하면 원본 데이터의 값에 영향을 미침.
  • Java는 모든 파라미터 전달에 Pass by Value를 사용.

 

Pass by Value

  • 파라미터를 전달하는 기본 메커니즘
    • 파라미터에 인자의 값이 복사됨.
    • 메소드 내부에서 변수 값을 변경 가능.
    • 메소드 내부에서 변경된 변수 값은 메소드 밖으로 영향을 주지 않음.
    • 파라미터는 반드시 같은 타입이거나, 호환되는 타입이어야 한다.
static void addOne(int i) {
   i++;
}
public static void main(String[] args) {
   int j = 5;
   addOne(j);
   System.out.println(j);   // 6이 아닌 5가 출력됨
}

 

 

가변 길이 목록 파라미터 사용

  • 파라미터에서 타입 뒤에 ...을 사용, 메소드에 하나만을 사용할 수 있다.
  • 같은 타입의 파라미터 여러 개를 배열로 변환하여 전달.
  • 다른 타입의 파라미터와 함께 쓸 경우, 파라미터 목록의 제일 마지막에 선언.
     ex) exampleMethod(String s, int... numbers)
public static int sumOfParameters(int... values) { // values는 int 타입의 여러 값을 받을 수 있다.
    int sum = 0;
    System.out.println("Count of parameters: " + values.length);
    for (int i: values) {
        i++;
        sum += i;
    }
    return sum;
}

/* 가변길이 파라미터를 사용하는 두 가지 방법, 똑같이 동작한다 */
public static void main(String[] args) {
    int result;
/* values에 int 타입 여러개를 배열로 변환하여 전달한다. */
    result = sumOfParameters(1,2,3); // 콤마(,)로 구분된 요소들의 목록
    result = sumOfParameters(new int[] {1,2,3}); // 배열
}

 

* 중요

  • Java에서는 값이 무조건 pass by value로 넘어간다. 
  • Java에서 배열객체힙(Heap)영역에 동적으로 할당된다. 따라서 스택 영역에는 이것들의 값이 저장되어 있는 힙 영역의 주소가 들어있다. 이걸 pass by value 하게 되면 마치 pass by reference와 같은 결과가 나온다.
  • Java에서 스택(Stack)영역에는 메소드 호출 시 생성되는 프레임(지역 변수, 매개 변수, 반환 주소 등)이 저장된다.

 

재귀(Recursive) 메소드 사용

   Java의 메소드는 상호 재귀적이다. 메소드 A가 메소드 B를 호출할 수 있고, 메소

  • 자기 자신(메소드)을 호출
  • 직접적 호출
  • 간접적 호출
  • 대표적인 알고리즘 문제: 피보나치 수열, 하노이 탑, factorial
/* 재귀 메소드 예시: Factorial 문제 */
static int factorial (int n) {
	if (n < 1) { // 재귀 메소드는 추가 호출없이 return하는 종료 조건이 있어야 한다.
    	return 1;
    }
    else {
    	return n * factorial(n - 1);
    }
}
// 재귀 메소드
public class Algorithm {

    public static int addNto10(int n) {
        int result = 0;
        for (int i=0; i<= 10; i++) {
            result += i;
        }
        return result;
    }

    public static int addNtoNRecur(int n) {
        if (n>10) {
            return 0; // int를 return 해야하니까 0
        }
        else {
            return addNtoNRecur(n+1) + n;
        }

    }

    public static void main(String[] args) {
        System.out.println(addNto10(1));
        System.out.println(addNtoNRecur(1));
    }
}

 

Chapter 3: 메소드 오버로딩(Method Overloading)

메소드 오버로딩 정의

  • Class 내에서 같은 이름을 사용하는 메소드.
  • 파라미터의 개수와 타입을 검사하여 구분.
  • Java에서 다형성을 표현하는 한 가지 방법.
    (메소드 오버로딩: 정적 바인딩, 메소드 오버라이딩: 동적 바인딩)
static int add(int i, int j) {
    return i + j;
}

static int add(int i, int j, int k) {
    return i + j + k;
}

public static void main(String[] args) {
    int i = add(1, 2);
    int j = add(1, 2, 3);
    System.out.println(i + j);
}

 

메소드 시그니처

  • 시그니처
    • 컴파일러가 클래스의 메소드를 구분하는데 사용.
    • 메소드 이름, 파라미터의 타입, 파라미터의 개수로 구성. ex) doSomething( int n )
    • 파라미터의 이름, 메소드의 return type은 시그니처에 영향을 미치지 않음.
/* 시그니처가 다른 3개의 메소드 */
static int doSomething() {
}

static int doSomething(int n) {
}

static int doSomething(int n, int p) {
}

/* 오류: 메소드 시그니처는 return type을 포함 X */
static int doSomething (int n) {
}

static String doSomething (int n) {
}

/* 오류: 메소드 시그니처는 파라미터 이름을 포함 X */
static int doSomething (int n) {
}

static int doSomething (int j) {
}

 

오버로드된 메소드 사용

  • 다른 파라미터가 필요한 유사한 메소드
  • 기존 코드에 새 기능 추가: 기존 코드를 광범위하게 변경하지 않고 새 기능 추가.

다른 파라미터가 필요한 유사한 메소드

 

Lab 5-2 메소드 오버로딩

참조: https://github.com/gikpreet/class-programming_with_java/blob/master/Module%2005%20%EB%A9%94%EC%86%8C%EB%93%9C%EC%99%80%20%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0/contents/19_lab_5-2.adoc

 

class-programming_with_java/Module 05 메소드와 파라미터/contents/19_lab_5-2.adoc at master · gikpreet/class-programming

Contribute to gikpreet/class-programming_with_java development by creating an account on GitHub.

github.com

/* Multipler.java */
public class Multiplier {
    public int apply(int left, int right) {
        return left * right;
    }
}
/* Adder.java */
class Adder {
    public int apply(int right, int left) {
        return right + left;
    }
}
/* Algorithm.java */
public class Algorithm {

    static final int addFrom1to10 = 55;

    public static int sigma(int start, int end, int step) {
        return accumulate(new Adder(), 0, start, end, step);
    }

    public static int pi(int start, int end, int step) {
        return accumulate(new Multiplier(), 1, start, end, step);
    }

    public static int accumulate(Adder binder, int init, int start, int end, int step) {
        int result = init;
        for(int i=start; i<=end; i+=step) {
            result = binder.apply(result, i);
        }
        return result;
    }

    public static int accumulate(Multiplier binder, int init, int start, int end, int step) {
        int result = init;
        for(int i=start; i<=end; i+=step) {
            result = binder.apply(result, i);
        }
        return result;
    }

    public static void main(String[] args) {

        System.out.println(sigma(1,10,1));
        System.out.println(pi(1,10,1));

	// 객체 생성은 Adder a = new Adder();인데 Adder a는 파라미터로, new Adder()는 인자로 쓴거다.
        // 함수를 호출해서 argument -> parameter로 보내는 거니까.
        System.out.println(accumulate(new Adder(), 0, 1, 10, 1));
        System.out.println(accumulate(new Multiplier(), 1, 1, 10, 1));
    }
}


실행 결과

55
3628800
55
3628800

 

 


 

[코딩 문제] Palindrom

2024.08.23 - [코딩 문제] - Palindrom

 

Palindrom

 

lightningtech.tistory.com

 

[코딩 문제] Anagram

2024.08.23 - [코딩 문제] - Anagram

 

Anagram

 

lightningtech.tistory.com

 


 

 

출처: https://github.com/gikpreet/class-programming_with_java/tree/master

 

GitHub - gikpreet/class-programming_with_java

Contribute to gikpreet/class-programming_with_java development by creating an account on GitHub.

github.com