Method 함수(function) 

👩🏻‍💻  특정 작업을 수행하는 일련의 문장들을 하나로 묶은 것

👩🏻‍💻  기본적으로 수학의 함수와 유사하며, 어떤 값을 입력하면 이 값으로 작업을 수행해서 결과를 반환

👩🏻‍💻  main 메서드는 '규칙'. 이 메서드 안에 실행되기를 기다리는 로직을 위치시켜야 한다. 

1)  메서드의 장점과 작성지침

  · 반복적인 코드를 줄이고 코드의 관리가 용이.

  · 반복적으로 수행되는 여러 문장을 메서드로 작성.

  · 하나의 기능을 위해 작성한 여러 코드를 하나의 단어로 표현할 수 있음. (추상화)

  · 하나의 메서드는 한 가지 기능만 수행하도록 작성하는 것이 좋음.

  · 메서드는 특정 동작을 하는 코드이기 때문에 이름을 동사로 시작   ex. getAge ()


2)  메서드 용어

  · 인수 (argument) : 메서드에 전달할 입력(input)을 의미

  · 매개변수 (parameter) : 인수를 받아서 저장하는 변수를 의미

  · 반환값 (return) : 메서드의 출력(output)을 의미. 

      ⚡️  return의 기능 1) 값을 반환  2) 함수를 종료 (반복문의 break와 비슷) 

  · 메서드 호출 : 메서드를 실제로 사용하는 것을 의미

 

사용 예제

 

   📍  3명의 신장, 체중, 나이의 최대값을 구해서 표시
         ✔️  메서드를 만들면 1) 소스가 줄어들어서 main 메서드의 기본 로직을 읽기 쉽고 2) 재사용을 할 수 있다

public class MyMethod_01 {

    static Scanner scanner = new Scanner(System.in);
    static int getMax(int a, int b, int c) { // a,b,c의 최대값을 반환
    	int max = a;
    	if(b > max) max = b;
    	if(c > max) max = c;
    	return max;
    }
    
    static void inputData(int[] height, int[] weight, int[] age) {
    	  for (int i = 0; i < 3; i++) {
  	    	System.out.print("[" + (i+1) + "] ");
  	    	System.out.print("신장: ");  height[i] = scanner.nextInt();
  	    	System.out.print("   체중: "); weight[i] = scanner.nextInt();
  	        System.out.print("   나이: ");  age[i]  = scanner.nextInt();
  	    }
    }

	public static void main(String[] args) {
		
		// 3명의 신장, 체중, 나이의 최대값을 구해서 표시.
		int[] height = new int[3];  // 신장
		int[] weight = new int[3];  // 체중
		int[] age = new int[3];     // 나이
		
		inputData(height, weight, age);
	    
/*	    // 신장의 최대값을 구한다
	    int maxHeight = height[0];
	    if (height[1] > maxHeight) maxHeight = height[1];
	    if (height[2] > maxHeight) maxHeight = height[2];
	    
	    // 체중의 최대값을 구한다
	    int maxWeight = weight[0];
	    if (weight[1] > maxWeight) maxWeight = weight[1];
	    if (weight[2] > maxWeight) maxWeight = weight[2];
	    
	    // 나이의 최대값을 구한다
	    int maxAge = age[0];
	    if (age[1] > maxAge) maxAge = age[1];
	    if (age[2] > maxAge) maxAge = age[2]; */
	    
	    int maxHeight = getMax(height[0], height[1], height[2]);  // 신장의 최대값
	    int maxWeight = getMax(weight[0], weight[1], weight[2]);  // 체중의 최대값
	    int maxAge = getMax(age[0], age[1], age[2]);  // 나이의 최대
	    
	    System.out.println("신장의 최대값은 " + maxHeight + "입니다." );
	    System.out.println("체중의 최대값은 " + maxWeight + "입니다." );
	    System.out.println("나이의 최대값은 " + maxAge + "입니다." );		

	}
}
 
사용 예제 2
public class MyMethod_03 {
	
	static int getMax(int a, int b) { // a,b의 최대값을 반환
		// return이 여러번 나와도 된다.
	    System.out.println("함수 시작");
	    if(a>b) 
	    	return a;
	    else
	    	return b;
	    // System.out.println("함수 종료") -> return 때문에 함수가 종료되기 때문에 출력되지 않음.
	}

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		
		System.out.print("정수 a : ");
		int a = scanner.nextInt();
		System.out.print("정수 b : ");
		int b = scanner.nextInt();
		
		System.out.println("최대값은 " + getMax(a,b) + "입니다.");
	    scanner.close();
	}
}

 


 3)  메서드의 선언과 구현

  🚀  메서드는 크게 두 부분 '선언부(header, 머리)'와 '구현부(body, 몸통)'로 이루어져 있다.

반환타입 메서드이름 (타입 변수명, 타입 변수명, ...)
{
  // 메서드 호출시 수행될 코드
}
int add (int a, int b) {
    int result = a + b ;
    return result; // 호출한 메서드로 결과를 반환한다.
}

 

메서드 선언부
(method declaration,
method header)
- '메서드의 이름'과 '매개변수 선언' 그리고 '반환타입'으로 구성되어 있다.
- 메서드가 작업을 수행하기 위해 어떤 값들을 필요로 하고 작업의 결과로 어떤 타입의 값을 반환하는지에 대한 정보를 제공
매개변수 선언
(prameter declaration)
- 매개변수는 메서드가 작업을 수행하는데 필요한 값들(입력)을 제공받기 위한 것이며, 필요한 값의 개수만큼 변수를 선언.
- 각 변수 간의 구분은 쉼표 ',' 를 사용. 두 변수의 타입이 같아도 변수의 타입을 생략하는 것 불가.
  ex. int add ( int x, y) {...}  // 에러. 매개변수 y의 타입이 없다.
메서드의 이름
(method name)
- 특정 작업을 수행하므로 메서드의 이름은 'add' 처럼 동사인 경우가 많다.
반환타입
(return type)
- 메서드의 작업수행 결과(출력)인 '반환값(return value)'의 타입을 적는다.
- 반환값이 없는 경우 'void'
메서드의 구현부
(method body)
- 메서드의 선언부 다음에 오는 괄호{}를 '메서드의 구현부'라고 .
- 메서드를 호출했을 때 수행될 문장들을 넣는다.
return 문 - 메서드의 반환타입이 'void'가 아닌 경우, 구현부{} 안에 'return 반환값;'이 반드시 포함되어 있어야 한다.
- 이 문장은 반환값을 호출한 메서드로 전달.
- 이 값의 타입은 반환타입과 일치하거나 적어도 자동 형변환이 가능한 것이어야 한다.
- 단 하나의 값만 반환할 수 있음.
지역변수
(local variable)
- 메서드 내에 선언된 변수들은 그 메서드 내에서만 사용할 수 있으므로 서로 다른 메서드라면 같은 이름의 변수를 선언해도 된다.
- 이처럼 메서드 내에 선언된 변수를 '지역변수'라고 한다.
 

public class ExMethod_02 {

	public int add(int a, int b) {
		int c = a + b;
		return c;
		// return 다음에 위치하는 데이터는 반드시 메서드의 리턴 타입과 일치해야 함.
		// return 3.5; // 리턴 타입과 다른 데이터형을 반환하면 오류가 발생. (자동 형변환은 가능)
	}

	public static void main(String[] args) {
	     int numb1 = 10;
	     int numb2 = 20;
	     int result = 0;
	     
	     ExMethod_02 method = new ExMethod_02();
	     result = method.add(numb1, numb2);
	     System.out.println("두수의 합은 " + result); // 메서드의 반환 값을 저장해서 출력.
	     System.out.println("두수의 합은 " + method.add(numb1, numb2)); // 메서드의 반환 값을 바로 출력
		
	}
}

 


4)  메서드의 호출

인자(argument)와 매개변수(parameter)
int result = add(1,2,3);    // 에러. 메서드에 선언된 매개변수의 개수가 다름 
int result = add(1.5, 2.3); // 에러. 메서드에 선언된 매개변수의 타입이 다름

 

    - 인자의 개수와 순서는 호출된 메서드에 선언된 매개변수와 일치해야 한다.

    - 인자는 메서드가 호출되면서 매개변수에 대입되므로, 인자의 타입은 매개변수의 타입과 일치하거나 자동형변환이 가능한 것이어야 함.

 

반환 타입

    - 반환타입이 void가 아닌경우, 메서드가 작업을 수행하고 반환한 값을 대입연산자로 변수에 저장하는 것이 보통이지만, 저장하지 않아도 문제가 되지 않는다.

 

메서드의 실행흐름
  • main 메서드에서 메서드 getAge를 호출
  • 호출시 지정한 인자들이 메서드 getAge의 매개변수 a,b에 각각 복사(대입) 
  • 메서드 getAge의 괄호 {} 안에 있는 문장들이 순서대로 수행
  • 메서드 getAge의 모든 문장이 실행되거나 return문을 만나면, 호출한 메서드(main메서드)로 되돌아와서 이후의 문장들을 실행

 

⚒️   메서드 호출방식

  A.  값에 의한 호출

  • 값에 의한 메서드 호출 방식은 메서드 호출 시에 값이 복사되어 전달
  • 메서드의 매개변수 타입이 '기본형 데이터'일 때 값에 의한 호출을 함.
💡  값 형식 (Value Type)

     -  변수가 값을 담은 데이터 형식, 스택 메모리 영역과 관련.

     -  코드 블록 안에서 생성된 모든 값 형식의 변수들은 프로그램 실행이 중괄호 "}"를 만나면 메모리에서 제거

public class CallByValue {

    static public int increase(int n) {
    	++n;
    	return n;
    }

	public static void main(String[] args) {
		int var1 = 100;
		int result = increase(var1);
		System.out.println("var1: " + var1 + ", result: " + result);		
	}
}

 

  • 메서드 increase() 호출 시에 n이라는 매개변수가 메모리에 생성되어 var1의 값인 100 이 복사되어 처리
  • 메서드 실행이 종료되면 매개변수 n은 메모리에서 소멸
  • 이 처럼 값에 의한 호출은 호출시 매개변수로 전달되는 값이 복사되어 전달. 따라서 var1의 값은 변하지 않음

 

B.  참조에 의한 호출

  • 매개변수의 타입이 참조형 타입일 때 사용, 참조에 의한 호출은 메서드 호출 시 참조 데이터의 위치가 매개변수에 전달
  • 값에 의한 호출은 메모리에 동일한 값을 복사 후 사용하지만 참조에 의한 호출은 메모리의 주소를 넘기기 때문에 값을 복사하지 않음
💡  참조 형식 Reference Type

       - 변수가 값 대신 값이 있는 곳의 위치(참조)를 담는 데이터 형식, 힙 메모리 영역과 관련

       - 힙 영역에 데이터를 저장하고, 스택 영역에는 데이터가 저장된 힙 메모리의 주소를 저장

       - 가비지 컬렉터가 프로그램 뒤에 숨어 동작하면서 힙에 더 이상 사용하지 않는 객체가 있으면 그 객체를 쓰레기로 간주하고 수거하는 기능을 함

          ex. class, interface, delegate, object, string

public class CallByRef {
	
	public static void increase(int[] array) {
		/* 배열을 매개변수로 받아서, 원래 저장된 값보다 1이 증가한 값으로 업데이트 */
		for(int i = 0; i < array.length; i++) {
			array[i]++;
		}
	}

	public static void main(String[] args) {
		int[] refArray = {100, 800, 1000}; // 배열 선언 및 초기화. 배열은 참조형 데이터
		
	    System.out.println("메서드 호출 전");
	    for(int i = 0; i < refArray.length; i++) {
	    	System.out.println("refArray[" + i + "]: " + refArray[i]);
	    }
	    
	    increase(refArray); // 리턴이 없음.
	    
	    System.out.println();
	    System.out.println("메서드 호출 후");
	    // 배열은 참조형이라 메서드 호출 후 값이 변경.
	    for(int i = 0; i < refArray.length; i++) {
	    	System.out.println("refArray[" + i + "]: " + refArray[i]);
	    }
	}
}

 

 

  C.  문자열에 의한 호출

  • 예외적으로 문자열을 전달하려면 참조형 데이터라도 값에 의한 호출을 함. 값에 의한 호출이기 때문에 값을 변경할려면 변경된 문자열을 리턴하고 호출한 쪽에서 값을 저장하면 됨
public class CallByString {

    public static String setAddress(String addr) {
    	addr = "경기도 수원시 장안구";
    	return addr;
    }
	
	public static void main(String[] args) {
	    String address = " 서울시 강남구 논현동";
	    
	    System.out.println("메서드 호출 전");
	    System.out.println("address: " + address); // address: 서울시 강남구 논현동
	    
	    address = setAddress(address);
	    
	    System.out.println("메서드 호출 후");
	    System.out.println("address: " + address); // address: 경기도 수원시 장안구
		
	}
}

 

 값 복사  VS  참조 복사
public class MyMethod_04 {

	public static void main(String[] args) {
		/* 깊은 복사. 값 복사. 기본형 변수
		 * deep copy
		 * 데이터 자체가 복사된다.
		 * 복사된 두 객체는 완전히 독립적인 메모리를 차지.
		 */
		int a = 1;
		int b = a;
		b++;
		
		System.out.println("a: " + a + ", b: " + b); // a: 1, b: 2
		
		/* 얕은 복사. 참조 복사. 참조형 변수
		 * shallow copy
		 * 값 자체를 복사하는 것이 아니라 주소값을 복사하여 같은 메모리를 가리키기 때문.
		 */
		int[] nums_01 = new int[1];
		nums_01[0] = 1;
		
		int[] nums_02 = nums_01;
		nums_02[0] = 2;
		
		System.out.println("nums_01[0]: " + nums_01[0] + ", nums_02[0]:" + nums_02[0]);
		// nums_01[0]: 2, nums_02[0]:2

	}
}
 
 

5)  return 문

  • 현재 실행중인 메서드를 종료하고 호출한 메서드로 되돌아간다.
  • 반환타입이 void 인 경우, return문 없어도 문제가 되지 않는다  ➡️  컴파일러가 메서드의 마지막에 자동적으로 추가해주기 때문
  • 결과로 사용되는 유형 : void, 기본자료형, 클래스형 등
public class ExMethod {

	public void print() {
	    System.out.println("메서드를 호출한다");
	    // 리턴 타입이 없더라도 return을 사용할 수 있음.
	    // 다만 return 다음에 값이 없어야 함.
	    // return의 의미는 이 부분에서 메서드 실행을 종료하고 복귀한다는 의미.
	    // return;
	}
	
	public static void main(String[] args) {
    
	    // 사용할 메서드가 있는 클래스의 인스턴스 선언
		ExMethod method = new ExMethod();
		method.print();
		method.print();
		method.print();

	}
}



 
반환값(return value)
int add(int x, int y) { 
    int result = x + y; 
    return x+y;
}

  -  반환값으로 주로 변수가 오긴 하지만 위의 코드처럼 'x+y' 수식이 올 수 있다. (수식의 결과가 반환됨)

  -  간단한 메서드의 경우 if문 대신 조건연산자(ex. 삼항연산자)를 사용하기도 함.

 

매개변수의 유효성 검사

 

  -  메서드의 구현부{}를 작성할 때, 제일 먼저 해야 하는 일이 매개변수의 값이 적절한 것인지 확인하는 것

       ➡️  타입만 맞으면 어떤 값도 매개변수를 통해 넘어올 수 있기 때문.

  -  적절하지 않은 값이 매개변수를 통해 넘어온다면 매개변수의 값을 보정하던가, 보정하는 것이 불가능하다면 return문을 사용해서 작업을 중단하고 호출한 메서드로 되돌아가야 한다.


예제 문제

 

  📍 밑변이 30, 높이가 10인 사각형의 넓이를 출력하세요
        * 단 메서드 calculator()를 호출해서 출력하세요

public class Ex_01_01 {
	public static void main(String[] args) {
		
		int width = 30;
		int height = 10;
		System.out.println("밑변이 "+ width + " 높이가 " + height + "인 사각형의 넓이는 " + calculator(width,height) + "입니다.");
	
    }
	
	static int calculator(int a, int b) {
    	System.out.println("계산을 시작합니다.");
        int area = a * b; // 밑변 * 높이 = 사각형의 높이
        return area;
	}
}

 

직각 삼각형 만들기 
 
public class Ex_01_02 {
	/* 
	 * 별이 출력되는 부분은 putStars() 메서드를 정의해서 구현하세요.
	 * 몇 단 : 4
	 * *
	 * **
	 * ***
	 * ****
	 */
     
	static void putStars(int limit) {
	    for( int i = 1; i <= limit; i++) {
	    	System.out.print("*");
	    }
	}
	
	public static void main(String[] args) {
	     Scanner scanner = new Scanner(System.in);
	    
	     System.out.println("좌하변이 직각인 직각삼각형을 표시합니다.");
	     System.out.print("몇 단 : ");
	     int n = scanner.nextInt();
	     
	     for(int i = 1; i <= n; i++) {
	    	 //putStars() 메서드 호출
	    	 putStars(i);
	    	 System.out.println();
	     }
	     scanner.close();
	}
}
 
 
 


6)  메서드 종류

매개변수, 반환 값 모두 있는 경우
int method(int a) { int b; return b; }

 

매개변수는 있는데, 반환 값이 없는 경우
void method(int a) { }

 

 

매개변수는 없는데, 반환 값이 있는 경우

 

int method() { int b; return b; }

 

 
매개변수, 반환 값 모두 없는 경우
void method() { }

 

 

 

 

 

 

* 내용 참고 : 학원강의 및 자바의정석 3rd

+ Recent posts