09009

[Java] 메서드 본문

Back-End/JAVA
[Java] 메서드
09009 2023. 3. 10.

메서드

• 작업을 수행하기 위한 명령문의 집합

•  어떤 값을 입력받아서 처리하고 그 결과를 돌려주는 것

•  하나의 메소드는 한 가지 기능만 수행하도록 작성하는 것이 좋다.


 

메서드를 정의하는 방법

리턴타입 메서드이름 (타입 변수명, 타입 변수명, ....)
{
		// 메서드 호출 시 수행될 코드

}


int add(int a, int b) {          // 선언부

    int result = a + b;          // 구현부
    return result;				// 호출한 메서드로 결과를 반환한다.
}

예제 소스코드

사용하려는 클래스명과 main으로 실행하는 클래스명이 일치할 경우에는 클래스명을 생략하여 사용할 수 있다.

package ch06;

public class Method2_ {
	static void cal(int x, int y) { // %d는 정수
		System.out.printf("%d + %d = %d\n", x, y, x + y);
		System.out.printf("%d * %d = %d\n", x, y, x * y);
	}
	static void cal(double x, double y) { // %f는 실수, 변수명은 중요하지 않음, 데이터형이 중요
		System.out.printf("%f + %f = %f\n", x, y, x + y);
		System.out.printf("%f * %f = %f\n", x, y, x * y);
	}
	public static void main(String[] args) {
		for(int i = 0; i < 10; i++) {
			int x = (int)(Math.random() * 10) + 1;
			int y = (int)(Math.random() * 10) + 1;
			cal(x, y); // 사용하려는 클래스명과 main으로 실행하는 클래스명이 일치할 때는 클래스명 생략 가능
			double a = (Math.random() * 10) ;
			double b = (Math.random() * 10) ;
			cal(a, b); // 전달되는 것은 변수명이 아니라 값
		
		}
	}
}
package ch06;

public class Method3 {
	 static void hello(String name) {
		 System.out.println("안녕하세요, " + name + "님");
	 }
	public static void main(String[] args) {
		String[] name = {"김연아","제니","보검","은우","로제"};
		for(String n : name) {
			hello(n); // static한 메서드는 객체를 생성하지 않고도 바로 사용할 수 있다.
		}
	}

}

Return문

! 주의사항 !

반환값이 있는 메서드는 return문이 반드시 있어야 한다.

package ch06;
class A2 {
//	void : 비어있음, 반환할 것이 없다.
	void add(int x, int y) {
		System.out.printf("%d + %d = %d\n",x, y, x + y);
	}
//	반환할 값이 정수
	int minus(int x, int y) {
		return x - y;
	}
//  String 반환할 값이 문자열
	String hello(String name) {
		return "안녕하세요, " + name + "님";
	}
}
public class Return1 {
	public static void main(String[] args) {
		String[] names = {"김연아", "제니", "보검", "은우", "로제"};
		
		A2 a2 = new A2();
		int x = 56; int y = 65;
		a2.add(x, y);
//		System.out.println(a2.minus(x, y)); 이렇게 쓰거나
		int k = a2.minus(x, y);
		System.out.println(k);
		
		for(String name : names) {
			System.out.println(a2.hello(name));
		}	
	}
}

 

return문은 때때로 메서드를 중간에 끊고 싶을 때 사용하기도 한다.

package ch06;
public class Return2 {
	public static void main(String[] args) {
		for(int i = 0; i < 10; i++) {
			int x = (int)(Math.random() * 10);
			int y = (int)(Math.random() * 10);
			cal(x, y);
		}
	}

	private static void cal(int x, int y) {
		System.out.printf("%d + %d = %d\n", x, y, x + y);
		System.out.printf("%d - %d = %d\n", x, y, x - y);
		if (y==0) {
			System.out.println("여기까지 하고 종료");
			return; // return : 메서드 종료, 메서드를 중간에 끊고 싶을 때 사용
		} else System.out.printf("%d / %d = %d\n", x, y, x / y);
		System.out.printf("%d * %d = %d\n", x, y, x * y);
	}
}

위의 소스코드에서 random하게 나온 정수 y가 0일 경우, return문을 작성하여 메서드가 끝까지 수행되지 않고 종료된다.

따라서, 덧셈과 뺄셈의 연산결과는 출력되지만 정수 y가 0일 경우에 실행되는 return문으로 인하여 else 이하문인 나눗셈과 곱셈은 출력되지 않는다.


Call By Value

main 메서드 안에 작성된 데이터가 기본형인 경우 메서드를 호출하였을 때 값을 전달한 것이지 주소를 전달한 것이 아니다.

출력 결과를 확인하였을 때 class B1에 있는 m1 메서드 안에서의 결과와 main 메서드 안에서의 결과가 다르다는 사실을 확인할 수 있다.

→  즉, main 메서드 안에서 작성된 데이터가 기본형인 경우, 따로 정의한 메소드 안에서 바뀐 결과는 원래 데이터에 영향을 주지 않는다.

package ch06;
class B1 {
	void m1(int x, int y) {  // 전달한 것은 x = 10, y = 20 
		x += 7; y += 5;
		System.out.println("m1 x = " + x);
		System.out.println("m1 y = " + y);
	}
}

public class CallByValue1 {
	public static void main(String[] args) {
		B1 a1 = new B1();
		int x = 10, y = 20; // 데이터가 기본형인 경우
		a1.m1(x, y); // 값 10, 20을 전달한 것이지 변수 x, y를 전달한 것이 아니다
		System.out.println("main x = " + x);
		System.out.println("main y = " + y);
	}
}

출력 결과

m1 x = 17
m1 y = 25
main x = 10
main y = 20

아래와 같이 두 변수의 값을 서로 바꾸는 소스 코드에서도 마찬가지이다. 

 

입력

package ch06;
class B2 {
	void m1(int a, int b) { // 전달한 것은 x = 10, y = 20
//	    CallByValue: 메소드 안에서 바뀐 결과는 원래 데이터에 영향을 주지 않는다.
//		a와 b값을 서로 교환해서 출력
		int temp;
		temp = a;
		a = b;
		b = temp;
		System.out.println("m1 x = " + a);
		System.out.println("m1 y = " + b);
	}
}

public class CallByValue2 {
	public static void main(String[] args) {
		B2 a1 = new B2();
		int x = 10, y = 20; 
		a1.m1(x,y);
		System.out.println("main x = " + x);
		System.out.println("main y = " + y);
	}
}

💻 출력 결과

 

m1 x = 20
m1 y = 10
main x = 10
main y = 20

main 메서드에서 두 기본형 변수를 정의하고 class B2에 작성된 m1 메서드를 호출하였을 때, m1 메서드 안에서의 결과는 바뀌었지만, main 메서드에서 출력된 결과는 원래 데이터에서 변하지 않았다는 것을 알 수 있다.

 


Call By Reference

위의 소스코드에서 데이터가 기본형인 경우에는 메서드에서 바뀐 결과는 원본 데이터에서 바뀌지 않았다는 것을 알 수 있었다.

하지만 참조형 데이터의 경우에는 어떨까? 참조형 데이터는 값을 전달하는 기본형과 달리 주소를 전달하기 때문에 메서드 안에서 결과가 바뀌면 원본 데이터도 바뀌게 된다.

 

✍ 입력

package ch06;
class C1 { 
	void m1(int[] num) {
		num[0] = 77; num[1] = 100; // 전달된 주소를 찾아가서 값을 변경
		for(int i = 0; i < num.length; i++) {
			System.out.println("m1 num["+i+"] = " + num[i]);
		}
	}
}

public class CallByRef1 {
	public static void main(String[] args) {
		C1 c1 = new C1();
		int[] num = {12, 34, 66}; // 배열은 참조형, 참조형 데이터는 주소를 전달한다.
		c1.m1(num);				 // call by reference: 참조형은 주소를 전달하므로 메서드에서 바뀌면 원본 데이터도 바뀐다.
		for(int i = 0; i < num.length; i++) {
			System.out.println("main num["+i+"] = " + num[i]);
		}
	}
}

 

💻 출력 결과

m1 num[0] = 77
m1 num[1] = 100
m1 num[2] = 66
main num[0] = 77
main num[1] = 100
main num[2] = 66

출력 결과에서 보이는 바와 같이 배열과 같은 참조형 데이터의 경우, m1 메서드 안에서 결과가 바뀐 것이 main 메서드에서도 적용되었다는 것을 알 수 있다.

 

객체의 경우에도 마찬가지이다.

 

✍ 입력

package ch06;
class C2 {
	int x, y;
	public void m1(C2 c) {
//		x와 y를 서로 교환하고 c.x, c.y를 출력
		int temp = c.x;
		c.x = c.y;
		c.y = temp;
		System.out.println("m1 x = " + c.x);
		System.out.println("m1 y = " + c.y);
	}
}
public class CallByRef2 {
	public static void main(String[] args) {
//		C2 c를 생성하여 c.x = 10, c.y = 20을 대입하고 m1() 메서드에 c를 전달
//		c.x와 c.y를 출력
		C2 c = new C2();
		c.x = 10; c.y = 20; // 객체도 참조변수이므로 주소를 전달, 참조변수는 원본데이터가 바뀌면 같이 바뀐다.
		c.m1(c);
		System.out.println("main x = " + c.x);
		System.out.println("main y = " + c.y);
	}
}

💻 출력 결과

 

m1 x = 20
m1 y = 10
main x = 20
main y = 10

객체도 참조형이기 때문에 주소를 전달하므로 메서드 안에서 결과가 바뀌면 원본 데이터도 바뀌게 된다.


메서드 오버로딩 (OverLoadding)

하나의 클래스에 같은 이름의 메소드를 여러 개 정의하는 것

오버로딩의 조건

 메소드의 이름이 같아야 한다.

 매개변수의 개수 또는 타입이 달라야 한다.

매개변수는 같고 리턴타입이 다른 경우는 오버로딩이 성립되지 않는다.

(리턴타입은 오버로딩을 구현하는데 아무런 영향을 주지 못한다.)

 

매개변수의 이름이 다른 것은 오버로딩이 아니다.

!! 오버로딩 성립 안됨 !!

int add(int a, int b) {
	return a+b;
}
	
int add(int x, int y) {
	return x+y;
}

 

리턴타입은 오버로딩의 성립조건이 아니다.

!! 오버로딩 성립 안됨 !!
int add(int a, int b) {
	return a+b;
}
	
long add(int a, int b) {
	return (long)(a+b);
}

오버로딩의 예시

package ch06;
class E1 {
	int add(int x, int y) {
		return x + y;
	}
	double add(double x, double y) {
		return x + y;
	}
	String add(String name) {
		return "안녕하세요 " + name + "님 !!!";
	}
}

public class OverLoadding1 {
	public static void main(String[] args) {
		E1 e = new E1();
		System.out.println(e.add("철수"));
		System.out.println(e.add(12, 67));
		System.out.println(e.add(3.14, 5.23));
	}
}

 

 

/

'Back-End > JAVA' 카테고리의 다른 글

[Java] collection  (0) 2023.03.11
[Java] Object 클래스, equals(), toString()  (2) 2023.03.11
[Java] 클래스 간의 관계 - 포함관계  (0) 2023.03.11
[Java] 상속  (0) 2023.03.11
[Java] 다형성, 오버라이딩 (1)  (0) 2023.03.10