프로그래밍 언어/JAVA

[JAVA] 자바의 메서드 Method

Rateye 2021. 1. 18. 14:17
728x90
반응형

메서드 Method

  • 객체의 동작(기능)을 담당하는 요소
  • 반드시 호출되어야만 사용 가능(호출당해서 작업을 수행하는 메서드 : Worker 메서드)
  • (특정 메서드를 호출하는 메서드 : Caller 메서드)
  • 메서드 구현부(바디) 내에서 작업을 수행하는 도중 작업을 중지하고 호출한 곳으로 되돌아가려면 return 문을 사용
  • 단, 리턴타입에 따라 return 문 뒤에 데이터를 명시할 수도 있고 return 문 자체를 생략할 수도 있음
  • 매개변수는 1개 이상의 변수를 선언할 수 있지만 리턴값은 1개만 리턴 가능(동시에 2개 이상 리턴 불가)

메서드 정의 기본 문법

[제어자] 리턴타입 메서드명([매개변수선언]...) { 
		// 메서드가 호출되면 실행될 코드들...
 		[return [값];]
}

제어자 : 생략이 가능하며, 차후에 배움

리턴타입 : 메서드 실행 후 리턴되는 결과값의 데이터타입 (리턴값이 없을 때 특수한 데이터타입인 void 를 사용)

메서드명 : 호출할 때 사용할 이름을 지정. 식별자 작성 규칙 적용

매개변수 : 메서드 호출 시 전달할 데이터를 저장할 변수 선언

  • 위의 요소가 포함되는 부분을 메서드 **헤더(선언부)**라고 함
  • 매개변수(Parameter, 파라미터)라고 하며 매개변수에 전달할 데이터를 전달인자(Argument, 아규먼트)라고 함

메서드 선언부 뒤의 중괄호{} 에 해당하는 부분은 메서드가 호출되면 실행될 코드들이 기술되는 부분이며 메서드 **바디(구현부)**라고 함

메서드 정의 형태에 따른 분류

  1. 매개변수도 없고, 리턴값도 없는 메서드
  2. 매개변수는 없고, 리턴값만 있는 메서드
  3. 매개변수만 있고, 리턴값은 없는 메서드
  4. 매개변수도 있고, 리턴값도 있는 메서드
	// 1. 매개변수도 없고, 리턴값도 없는 메서드 정의
	// => 리턴값이 없으므로, 리턴타입 부분에 특수 자료형인 void 를 명시
	// => 매개변수가 없으므로 메서드 선언부 소괄호() 안을 비워둠
	public static void sister_1() {
		System.out.println("동생 : 오빠가 불 끄라고 시켜서 불을 껐다!");
		
		// 리턴타입이 void 인 메서드에는 return 문을 사용은 가능하나
		// return 문 뒤에 아무런 데이터도 지정하지 못함
		return; // 현재 메서드 수행을 종료하고 돌아가라는 의미(생략 가능)
	}
	
	// 2. 매개변수는 없고, 리턴값만 있는 메서드 정의
	// => 리턴값이 있으므로, 리턴값에 해당하는 자료형을 명시
	// => 매개변수가 없으므로 메서드 선언부 소괄호() 안을 비워둠
	public static String sister_2() {
		System.out.println("동생 : 오빠가 물 떠오라고 시켰다!");
		String water = "물";
		System.out.println("동생 : 오빠에게 물을 떠다 줬다!");
		
		// 리턴값이 있으므로 메서드 작업 종료 부분에 return 을 명시하고
		// return 문 뒤에 리턴할 데이터(변수 또는 리터럴)를 명시
		return water; // 변수 지정 또는
	//		return "물"; // 리터럴 지정 가능
		// => return 할 데이터타입이 String 이므로 리턴타입에 String 명시
	}
	
	// 3. 매개변수만 있고, 리턴값은 없는 메서드 정의
	// => 리턴값이 없으므로 리턴타입에 void 명시
	// => 메서드 호출 시 정수 1개를 전달하므로 정수를 저장할 매개변수 선언
	public static void sister_3(int money) {
		// => Caller 로부터 전달받은 정수 데이터를 매개변수 money 에 저장
		//    (메서드 내에서 int money = X; 형태의 문장과 동일하게 사용됨)
		System.out.println("동생 : 오빠가 준 돈 = " + money + "원");
		money -= 200;
		System.out.println("동생 : 오빠가 준 돈으로 과자를 사먹었다!");
		System.out.println("동생 : 남은돈 = " + money + "원");
		
		// 리턴타입이 void 이므로 리턴할 데이터가 없음
		// return; 형태로 명시하거나 생략 가능
		//		return;
	}
	
	// 4. 매개변수도 있고, 리턴값도 있는 메서드 정의
	// => 리턴값이 있으므로, 리턴타입 부분에 리턴할 데이터타입 명시
	// => 매개변수가 있으므로 소괄호() 안에 전달받은 데이터 저장 변수 선언
	public static String sister_4(int money) {
		// 외부로부터 전달받은 정수 200 이 매개변수 money 에 저장됨
		System.out.println("동생 : 오빠가 과자 사오라고 " + money + "원을 줬다!");
		money -= 200;
		System.out.println("동생 : 새우깡 사고 " + money + "원이 남았다!");
		
		// 리턴타입이 String 이므로 String 타입 데이터가 리턴되어야함!
		return "새우깡"; 
	}
	
	// 5. 매개변수가 2개 이상인 메서드
	// => 매개변수가 여러개일 때 해당 갯수와 타입 만큼 변수 선언 필요
	//    주의사항! 전달된 데이터의 순서대로 선언해야함!
	public static String sister_5(String snack, int money) {
		// "새우깡", 1000 을 전달했으므로 String, int 순으로 변수 선언 필요
		System.out.println("동생 : 오빠가 준 과자 = " + snack);
		System.out.println("동생 : 오빠가 준 돈 = " + money + "원");
		money -= 1000;
		snack = "쿠쿠다스";
		return snack;
	}
		// 1. 매개변수도 없고, 리턴값도 없는 메서드 호출
		System.out.println("동생아! 불 좀 꺼라!");
		// => sister_1() 메서드는 매개변수가 없으므로
		//    메서드 호출 시 소괄화 내부에 아무 데이터도 전달하지 못함
		sister_1();
		System.out.println("동생이 불을 끄고 갔다!");
		
		System.out.println("=========================================");
		
		// 2. 매개변수는 없고, 리턴값만 있는 메서드 호출
		// => sister_1() 메서드는 매개변수가 없으므로
		//    메서드 호출 시 소괄호 내부에 아무 데이터도 전달하지 못함
		// => 리턴값이 있으므로 변수에 리턴값을 저장하거나
		//    출력문 등에 바로 사용할 수도 있음
		System.out.println("동생아! 물 좀!");
		String result = sister_2(); // 리턴값을 result 변수에 저장
		System.out.println("동생이 가져다 준 것 : " + result);
		// -----------------------------------------
		// 리턴값을 출력문에 바로 사용 가능
		System.out.println("동생이 가져다 준 것 : " + sister_2());
		// -----------------------------------------
		// 주의! 리턴값이 없는 메서드는 변수에 저장 또는 출력문에 사용 불가
		//		result = sister_1(); // 오류 발생! 리턴타입이 void 이므로 저장 불가
		
		System.out.println("=========================================");
		// 3. 매개변수만 있고, 리턴값은 없는 메서드
		System.out.println("동생아! 200원 줄테니 과자 사먹어라!");
		// => 매개변수가 있으므로 메서드 호출 시점에서 소괄호에 데이터 전달 필요
		//    (전달할 데이터는 변수 또는 리터럴 사용 가능)
		sister_3(200); // 메서드 호출 시 정수 200을 전달
		
		//		int money = 200;
		//		sister_3(money); // 메서드 호출 시 정수형 변수를 전달
		
		// => 메서드 파라미터(매개변수) 부분에 아무것도 전달하지 않으면
		//		sister_3(); // 오류 발생! 매개변수 타입 및 갯수와 일치해야함
		// The method sister_3(int) in the type Ex is not applicable for the arguments ()
		
		System.out.println("=========================================");
		// 4. 매개변수도 있고, 리턴값도 있는 메서드
		System.out.println("동생아! 200원 줄테니 새우깡 좀 사다 도!");
		// sister_4() 메서드 호출 시 매개변수에 전달할 데이터가 필요
		String snack = sister_4(500); // 메서드 호출 시 정수 200 전달
		// => 메서드 작업 종료 후 문자열이 리턴되므로 변수 snack 에 저장
		System.out.println("동생이 사다준 것 : " + snack);
		
		System.out.println("=========================================");
		// 5. 매개변수가 2개 이상인 메서드
		// => 3번 또는 4번 유형 메서드에서 전달할 데이터가 2개 이상인 경우
		// => 각 데이터를 콤마(,)로 구분하여 전달
		System.out.println("동생아! 1000원 줄테니 새우깡을 쿠쿠다스로 바꿔온나!");
		snack = sister_5("새우깡", 1000); // String, int 순으로 전달
		System.out.println("동생이 바꿔다 준 것 : " + snack);

 

반응형

메서드 오버로딩 Method Overloading = 메서드 다중 정의

  • 시그니처(리턴타입, 메서드명, 매개변수 중) 매개변수(파라미터)가 다른 메서드를 여러번 정의하는 것
  • 동일한 작업을 수행하는 메서드의 매개변수 타입이 다를 때 메서드 이름을 별도로 구분하지 않고, 같은 이름의 메서드를 매개변수만 달리 하여 여러번 정의하는 것
  • 메서드 호출 시점에서 전달되는 데이터 타입에 따라 매개변수 타입이 일치하는 해당 메서드를 자동으로 호출함
  • 매개변수 이름만 다르거나, 리턴타입만 다른 것은 오버로딩이 아님
class OverloadingMethod {
	// 정수 1개를 전달받아 절대값을 계산하여 출력하는 abs() 메서드 정의
	// => int, double, long 타입에 대한 각 메서드를 abs() 이름으로 통일
	//    단, 매개변수 타입만 int, double, long 으로 구분
	public void abs(int num) {
		// 전달받은 정수 num 이 음수일 경우 양수로 변환 후 출력
		// 아니면 그대로 출력
		if(num < 0) {
			num = -num;
		}
		
		System.out.println("num = " + num);
	}
	
	// 매개변수의 타입이 같고, 변수명만 다른 것은 오버로딩이 아니다!
	//	public void abs(int num2) {} // 컴파일 에러 발생!
	
	// 매개변수가 같고, 리턴타입만 다른 것은 오버로딩이 아니다!
	//	public int abs(int num) {} // 컴파일 에러 발생!
	
	// int형이 아닌 다른 타입 매개변수를 선언하면 오버로딩이 성립됨!
	public void abs(double num) {
		// 전달받은 실수 num 이 음수일 경우 양수로 변환 후 출력
		// 아니면 그대로 출력
		if(num < 0) {
			num = -num;
		}
		
		System.out.println("num = " + num);
	}
	
	public void abs(long num) {
		// 전달받은 long 타입 정수 num 이 음수일 경우 양수로 변환 후 출력
		// 아니면 그대로 출력
		if(num < 0) {
			num = -num;
		}
		
		System.out.println("num = " + num);
	}
}
class NormalMethod {
	
	// 정수 1개를 전달받아 절대값을 계산하여 출력하는 abs() 메서드 정의
	public void abs(int num) {
		// 전달받은 정수 num 이 음수일 경우 양수로 변환 후 출력
		// 아니면 그대로 출력
		if(num < 0) {
			num = -num;
		}
		
		System.out.println("num = " + num);
	}
	
	// double 타입 실수를 전달받는 메서드를 별도로 정의
	// => 메서드명도 식별자이므로 중복되면 안된다!
	public void dAbs(double num) {
		// 전달받은 정수 num 이 음수일 경우 양수로 변환 후 출력
		// 아니면 그대로 출력
		if(num < 0) {
			num = -num;
		}
		
		System.out.println("num = " + num);
	}
	
	// long 타입 정수를 전달받는 메서드 별도 정의
	public void lAbs(long num) {
		// 전달받은 정수 num 이 음수일 경우 양수로 변환 후 출력
		// 아니면 그대로 출력
		if(num < 0) {
			num = -num;
		}
		
		System.out.println("num = " + num);
	}
	
	// 데이터 1개를 전달받아 출력하는 print() 메서드
	public void intPrint(int data) {
		System.out.println(data);
	}
	
	public void StringPrint(String data) {
		System.out.println(data);
	}
	
	public void doublePrint(double data) {
		System.out.println(data);
	}
	
}
		NormalMethod nm = new NormalMethod();
		nm.abs(-10);
		nm.dAbs(-3.3);
		nm.lAbs(-30L);
		
		System.out.println("------------------------");
		
		OverloadingMethod om = new OverloadingMethod();
		om.abs(-10); // public void abs(int num) {} 메서드가 호출됨
		om.abs(-3.3); // public void abs(double num) {} 메서드 호출됨
		om.abs(-30L); // public void abs(long num) {} 메서드 호출됨
		// => 즉, 메서드 파라미터 전달 시, 매개변수를 구분할 수 있으면
		//    메서드 오버로딩이 성립되는 것으로 간주하고 오류 발생 없음!

메서드 오버로딩(매개변수 갯수 또는 순서가 다른 메서드)

  • 매개변수의 타입이 같더라도 갯수가 다르면 오버로딩이 성립됨 단, 타입이 같은 매개변수간의 순서 변경은 오버로딩이 아님
class OverloadingMethod {
	// 매개변수 갯수가 다른 메서드 오버로딩
	// 정수 2개를 전달받는 print() 메서드 정의
	public void print(int n1, int n2) {
		System.out.println(n1 + ", " + n2);
	}
	
	// 정수 3개를 전달받는 print() 메서드 정의
	public void print(int n1, int n2, int n3) {
		System.out.println(n1 + ", " + n2 + ", " + n3);
	}
	
	// ------------------------------------------------------
	// 정수 1개(count)와 문자열(name) 2 ~ 4개까지 전달받는 
	// print2() 메서드 정의 
	public void print2(int count, String name1, String name2) {
		System.out.println(count + " : " + name1 + ", " + name2);
	}
	 
	public void print2(int count, String name1, String name2, String name3) {
		System.out.println(count + " : " + 
				name1 + ", " + name2 + ", " + name3);
	}
	
	public void print2(	int count, 
			String name1, String name2, String name3, String name4) {
		System.out.println(count + " : " + 
				name1 + ", " + name2 + ", " + name3 + ", " + name4);
	}
	
	// ------------------------------------------------------
	public void sum(int num1, double num2) {
		System.out.println(num1 + " + " + num2 + " = " + (num1 + num2));
	}
	
	public void sum(double num1, int num2) {
		System.out.println(num1 + " + " + num2 + " = " + (num1 + num2));
	}
	
	public void sum(int num1, int num2) {
		System.out.println(num1 + " + " + num2 + " = " + (num1 + num2));
	}
	
	// 같은 데이터타입끼리의 순서는 바꿀 수 없다! = 오버로딩 성립 X
//	public void sum(int num2, int num1) {
//		System.out.println(num1 + " + " + num2 + " = " + (num1 + num2));
//	}
	
}
OverloadingMethod om = new OverloadingMethod();
		// 반드시 호출하려는 메서드의 매개변수 갯수 및 타입이 일치해야함
		om.print(10, 20);
		om.print(10, 20, 30);
//		om.print(10, 20, 30, 40); // 오류 발생!
		
		om.print2(2, "홍길동", "이순신");
		om.print2(3, "홍길동", "이순신", "강감찬");
		om.print2(4, "홍길동", "이순신", "강감찬", "김태희");
		
		// 정수 1개, 실수 1개를 전달받아 덧셈 결과를 출력하는 sum() 메서드
		om.sum(1, 3.14);
		om.sum(3.14, 1);

메서드 오버라이딩 Method Overriding

  • 슈퍼클래스로부터 상속받은 메서드와 시그니쳐가 동일한 메서드를 서브클래스에서 새롭게 재정의 하는 것
  • 기존의 슈퍼클래스의 메서드를 수정하여 덮어쓰는 것
  • 오버라이딩 이후에는 슈퍼클래스의 메서드는 은닉되어 보이지 않음
  • 오버라이딩을 ****사용하는 이유 코드의 재사용성이 향상되고, 통일성이 제공됨
  • 오버라이딩 단축키 : Alt + Shift + S -> V 자동 오버라이딩을 ****수행하면 @Override 어노테이션이 붙게 됨 오버라이딩 규칙을 위반하면 오류가 발생하도록 함 (ex. 오버로딩, 오타로 인한 이름 입력 오류 등)

오버라이딩 작성 규칙

  1. 슈퍼클래스의 메서드 시그니쳐(이름, 파라미터, 리턴타입)가 완벽하게 동일해야한다.
  2. 슈퍼클래스 메서드의 접근제한자보다 범위가 좁아질 수 없다.
    (ex. 슈퍼클래스가 public 이면 서브클래스도 public 이어야함)
    (ex2. 만약 protected 이면 서브클래스는 protected, public 가능)
class Parent4 {
	
	public void parentPrn() {
		System.out.println("슈퍼클래스의 parentPrn() 메서드!");
	}
	
}
// Child4 클래스 정의 - Parent4 클래스를 상속
class Child4 extends Parent4 {
	
	public void childPrn() {
		System.out.println("서브클래스의 childPrn() 메서드!");
	}
	
	// 슈퍼클래스로부터 상속받은 parentPrn() 메서드 오버라이딩
	// => 리턴타입, 이름, 파라미터가 모두 동일해야함
	// => 접근제한자는 좁아질 수 없음
	public void parentPrn() {
		System.out.println("서브클래스에서 오버라이딩 된 parentPrn() 메서드!");
	}
	
}
class Car {
	
	public void speedUp() {
		System.out.println("자동차 속력 증가!");
	}

	public void speedDown() {
		System.out.println("자동차 속력 감소!");
	}
	
	public void addFuel() {
		System.out.println("자동차 연료 공급!");
	}
	
}
// 디젤 자동차 - Car 클래스 상속
class DieselCar extends Car {
	// Car 클래스의 메서드를 오버라이딩하여 DieselCar 만의 기능을 재정의
	public void speedUp() {
		System.out.println("DieselCar 방식으로 속력 증가!");
	}

	public void speedDown() {
		System.out.println("DieselCar 방식으로 속력 감소!");
	}
	
	public void addFuel() {
		System.out.println("주유소에서 디젤 연료 공급!");
	}
}
// 전기 자동차 - Car 클래스 상속
class ElectricCar extends Car {
	// Car 클래스의 메서드를 오버라이딩하여 ElectricCar 만의 기능을 재정의
	// 자동 오버라이딩 단축키 : Alt + Shift + S -> V
	@Override
	public void speedUp() {
		System.out.println("ElectricCar 방식으로 속력 증가!");
	}

	@Override
	public void speedDown() {
		System.out.println("ElectricCar 방식으로 속력 감소!");
	}

	@Override
	public void addFuel() {
		System.out.println("전기 충전소에서 배터리 충전!");
	}
	
	
	
}
Child4 c = new Child4();
		c.childPrn(); // 서브클래스에서 정의한 메서드
		c.parentPrn(); // 서브클래스에서 오버라이딩 된 메서드
		// => 슈퍼클래스(Parent4)의 parentPrn() 메서드는 보이지 않으므로
		//    접근이 불가능하게 됨(은닉됨)
		
		System.out.println("============================");
		// Car 클래스를 상속받은 DieselCar 와 ElectricCar 클래스의
		// 인스턴스를 생성하여 오버라이딩 된 메서드를 각각 호출
		DieselCar dc = new DieselCar();
		dc.speedUp();
		dc.speedDown();
		dc.addFuel();
		
		ElectricCar ec = new ElectricCar();
		ec.speedUp();
		ec.speedDown();
		ec.addFuel();

 

가변 인자(비정형 인자, Variable Arguments)

  • 메서드 정의 시 파라미터(매개변수)에 전달되는 인자의 갯수가 유동적일 때 일정 갯수가 정해져 있지 않으므로 변수 선언이 어렵다. 따라서, 이렇게 동적인 인자의 갯수를 모두 처리할 수 있도록 가변 인자를 사용하여 변수를 선언하면 동일한 타입의 갯수가 제한이 없는 인자를 모두 전달받을 수 있음
  • 가변 인자 형태로 선언되는 매개변수는 ****전달받은 데이터를 해당 이름을 가진 배열 형태로 관리함
  • 가변 인자에 전달될 데이터는 0개부터 자유롭게 전달 가능

주의 사항!

가변 인자는 마지막 파라미터로 단 한 번만 사용 가능하다.

가변 인자를 사용한 메서드 정의 기본 문법

 [제한자] 리턴타입 메서드명(데이터타입... 변수명) {
 	// => 전달되는 데이터들이 가변인자 변수명의 배열로 관리됨
 }
class VariableArguments {
	// 가변인자(비정형인자)를 활용한 메서드 오버로딩
	// => 하나의 메서드 정의만으로 갯수가 다른 파라미터를 모두 처리 가능
	public void varargsPrint(int...nums) {
		// 외부로부터 전달되는 정수형 데이터는 갯수 제한 없이
		// 모두 nums 이름을 갖는 배열에 저장됨
		// => 반복문을 사용하여 배열 내의 모든 데이터에 접근 가능
		// 1) 일반 for문
		//		for(int i = 0; i < nums.length; i++) {
		//			System.out.print(nums[i] + " ");
		//		}
		
		// 2) 향상된 for문
		for(int num : nums) {
			System.out.print(num + " ");
		}
		
		System.out.println();
		
	}
	
	// 주의사항!
	// 가변인자는 마지막 인자로 단 한 번만 사용 가능
	public void varargsPrint2(String title, int...nums) {}
	// => 가변인자 앞에 다른 매개변수가 있더라도, 마지막이 가변인자면 OK
	
	//	public void varargsPrint2(int...nums, String title) {} // 오류 발생!
	// => 가변인자 뒤에 다른 매개변수가 올 수 없다!
	
	//	public void varargsPrint2(int...nums, String...title) {} // 오류 발생!
	// => 가변인자 뒤에 다른 매개변수가 올 수 없으므로
	//    2개 이상의 가변인자 사용도 불가능하다!
	
	// ----------------------------------------------------------
	// 일반 메서드 오버로딩
	// 정수 2개(n1, n2)를 전달받아 출력하는 print() 메서드 정의
	public void normalPrint(int n1, int n2) {
		System.out.println(n1 + ", " + n2);
	}
	
	// 정수 3개(n1, n2, n3)를 전달받아 출력하는 print() 메서드 정의
	public void normalPrint(int n1, int n2, int n3) {
		System.out.println(n1 + ", " + n2 + ", " + n3);
	}
	// => 전달되는 데이터가 2개 또는 3개의 경우에만 메서드가 호출되고
	//    0개, 1개, 또는 4개 이상의 경우에는 일치하는 매개변수가 없으므로
	//    호출되지 못하고 오류가 발생한다!
}
VariableArguments va = new VariableArguments();
		//		va.normalPrint(); // 오류 발생
		//		va.normalPrint(10); // 오류 발생
		va.normalPrint(10, 20);
		va.normalPrint(10, 20, 30);
		//		va.normalPrint(10, 20, 30, 40); // 오류 발생
		
		// 가변인자를 사용한 메서드 호출 시 전달할 파라미터 갯수 제한 없음
		va.varargsPrint(10);
		va.varargsPrint(10, 20);
		va.varargsPrint(10, 20, 30);
		va.varargsPrint(10, 20, 30, 40);
		va.varargsPrint(); // 전달할 데이터가 없어도 호출 가능

 

728x90
반응형