개요
현실의 객체가 하는 동작을 프로그래밍화 한 것을 메서드라고 한다.
어떤 작업을 수행하는 명령문의 집합으로 볼 수 있다.
반복적으로 사용되는 코드의 중복 방지를 위해 메서드를 사용한다.
이를 통해 프로그램의 재사용성을 높여 코드의 양을 줄일 수 있고 유지 보수가 용이하다.
주로 말하는 함수가 메서드라고 볼 수 있다.
즉, 어떤 값을 입력 받아서 작업을 진행하고 결과를 돌려주는 역할을 한다.
입력을 받는 것과 결과를 돌려주는 것은 생략할 수 있다.
[접근제어자] [static] 반환타입 메서드이름(매개변수) {
// 메서드 본문 (로직)
return 반환값; // 반환타입이 void면 return 생략 가능
}
메서드는 위와 같은 형태로 정의한다.
선언부
메서드를 호출한 곳으로 반환되는 값의 타입을 정한다.
만약 아무것도 리턴하지 않을 경우 void로 작성해 주면 된다.
결과를 받을 때 묵시적인 형 변환이 적용된다.
또한 리턴 타입은 하나만 적용이 가능하다.
메서드 이름은 수행하는 작업을 쉽게 파악하도록 의미 있는 이름을 사용하는 것을 권장한다.
메서드 호출 시점에 넘겨주고자 하는 변수가 있다면 메서드의 파라미터로 전달하면 된다.
별도의 파라미터가 필요가 없다면 생략하는 것도 가능하다.
파라미터 전달 시 묵시적 형변환이 적용된다.
만약 메서드 선언 시 동일 타입의 인자가 몇 개가 들어올 지 예상할 수 없을 경우 ...을 사용할 수 있다.
class Test {
public void add(int... params) {
int sum = 0;
for (int i : params) sum += i;
System.out.println(sum);
}
}
public class Main {
public static void main(String[] args) {
Test test = new Test();
test.add(1, 2, 3);
test.add(1, 2, 3, 4, 5, 6);
test.add(1, 2, 3, 4, 5, 6, 7, 8, 9);
}
}
또한 가변 길이 배열을 파라미터로 전달할 수 있다.
import java.util.ArrayList;
import java.util.Arrays;
class Test {
public void add(ArrayList<Integer> params) {
int sum = 0;
for (int i : params) sum += i;
System.out.println(sum);
}
}
public class Main {
public static void main(String[] args) {
Test test = new Test();
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 1; i < 10; i++) list.add(i);
test.add(list);
}
}
구현부
구현부는 중괄호 내에서 처리해야 하는 내용, 즉 비즈니스 로직을 작성한다.
마지막에는 선언된 리턴 타입에 해당하는 값을 return 문장과 함께 반환해야 한다.
값 반환 시에는 묵시적 형 변환이 적용된다.
리턴 타입이 void여서 반환할 값이 없을 경우 return 문장을 생략 가능하다.
메서드 수행 도중 return 문장을 만나거나 마지막 문장을 수행하는 경우 메서드는 종료된다.
조건문을 사용해 return할 경우 모든 조건에서 return이 필요하다.
public class Main {
public static void main(String[] args) {
System.out.println(calc(5, 7, '+'));
System.out.println(calc(15, 7, '-'));
System.out.println(calc(5, 7, '*'));
System.out.println(calc(15, 7, '/'));
System.out.println(calc(15, 7, '%'));
}
public static int calc (int a, int b, char op) {
if (op == '+') return a + b;
else if (op == '-') return a - b;
else if (op == '*') return a * b;
else if (op == '/') {
if (b == 0) {
System.out.println("0으로 나누면 안되지? 0받아라");
return 0;
}
return a / b;
}
else if (op == '%') return a % b;
return 0;
}
}
메서드 호출
메서드를 호출할 때는 반드시 메서드의 선언부에 맞춰 호출해야 한다.
- 메서드 이름 : 반드시 동일
- 파라미터 : 선언된 파라미터의 개수는 반드시 동일, 타입은 promition 적용 가능
메서드 접근 시 멤버 변수와 마찬가지로 static 또는 non static상태를 구분해서 호출해야 한다.
🔍 1. static 멤버 (정적 멤버)
- 클래스에 속함 (객체가 아닌 클래스 자체에 속함)
- 객체를 생성하지 않아도 호출 및 사용 가능
- 프로그램 실행 시 클래스가 메모리에 로드될 때 한 번만 메모리에 할당
- 모든 인스턴스가 같은 메모리 공간을 공유
🔍 2. non-static 멤버 (인스턴스 멤버)
- 객체에 속함 (객체가 생성될 때마다 새롭게 메모리에 할당)
- 각 객체마다 별도의 메모리 공간을 가짐
- 호출하려면 객체를 생성해야 한다.
메서드 호출 스택
스택은 선입 후출의 구조를 갖는다.
- 각각의 메서드 호출 시 마다 메서드 동작을 위한 메모리 상자를 하나씩 할당한다.
- 상자 내부에는 메서드를 위한 파라미터 변수 등 로컬 변수가 구성되어 있다.
- 만약 main에서 A메서드를 호출 후 A메서드 내부에서 B메서드를 호출 시 B 실행을 위한 메모리 상자를 쌓는다.
- 언제나 맨 위에 있는 메모리 상자만 활성화가 되어 있는 상태이다. 현재는 B 메모리 상자만 활성화 되어 있다.
- 이 때 A메서드는 동작이 끝나지 않고 잠시 정지된 상태이다.
- B가 리턴하게 되면 B를 위한 상자가 제거되며 메모리를 운영체제에 반납하게 된다.
- 이제 A 메모리 상자가 최상위가 되어 A메서드의 동작이 재개가 된다.
기본형 변수와 참조형 변수
자바에서는 기본적으로 메서드 호출 시 파라미터로 입력된 값을 복사해서 전달한다.
이를 call by value형식이라고 하는데 매개변수로 전달된 값을 변경하여도 원본에는 변경이 되지 않는다.
따라서 클래스의 객체 생성 후 해당 객체를 매개변수로 직접 전달하게 되면 원본에 접근할 수 있다.
✅ 예시: 기본 타입 (값 복사)
public class Main {
public static void main(String[] args) {
int num = 10;
changeValue(num);
System.out.println("main에서 num: " + num); // 여전히 10
}
public static void changeValue(int x) {
x = 20;
System.out.println("changeValue에서 x: " + x); // 20
}
}
✅ 예시: 참조 타입 (주소 복사)
class Person {
String name;
}
public class Main {
public static void main(String[] args) {
Person person = new Person();
person.name = "Alice";
changeName(person);
System.out.println("main에서 name: " + person.name); // Bob
}
public static void changeName(Person p) {
p.name = "Bob";
System.out.println("changeName에서 name: " + p.name); // Bob
}
}
메서드 오버로딩
동일한 기능을 수행하는 메서드의 추가 작성을 오버로딩이라고 한다.
일반적으로 메서드 이름은 기능별로 의미 있게 정한다.
동일한 기능을 여러 형태로 정의해야 할 때 메서드 오버로딩을 사용한다.
즉, 같은 이름의 메서드를 매개변수의 종류나 개수를 다르게 하여 여러 개 정의하는 것을 의미한다.
메서드 오버로딩은 컴파일 시간(Compile-time)에 결정되며, 메서드 호출 시 전달된 인자의 타입과 개수에 따라 알맞은 메서드가 선택된다.
✅ 메서드 오버로딩 규칙
- 메서드 이름은 동일해야 한다.
- 매개변수의 개수, 타입, 순서 중 하나가 달라야 한다.
- 반환 타입은 오버로딩을 결정짓는 요소가 아니다.
- 접근 제어자(public, private)는 달라도 된다.
public class Main {
public static void main(String[] args) {
System.out.println(add(10, 20)); // 정수 덧셈 (30)
System.out.println(add(5.5, 4.5)); // 실수 덧셈 (10.0)
System.out.println(add(1, 2, 3)); // 세 개의 정수 덧셈 (6)
System.out.println(add(10, " apples")); // 문자열 결합 ("10 apples")
}
public static int add(int a, int b) {
return a + b;
}
// 실수 덧셈
public static double add(double a, double b) {
return a + b;
}
// 세 개의 정수 덧셈
public static int add(int a, int b, int c) {
return a + b + c;
}
// 정수 + 문자열 덧셈
public static String add(int a, String b) {
return a + b;
}
}
add라는 메서드 명은 모두 같지만 반환 타입이 다르거나, 매개변수의 개수, 타입이 다른 것을 볼 수 있다.
add함수의 리턴 값을 출력하는 println함수 마저도 하나씩 타고 들어가면 매개변수 타입이 모두 다른 것을 볼 수 있다.
public void println(int x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(double x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(String x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
'웹(WEB) > 자바(JAVA)' 카테고리의 다른 글
[Java] 자바 생성자, this (1) | 2024.12.28 |
---|---|
[Java] 자바 변수의 선언 위치에 따른 분류 (0) | 2024.12.28 |
[Java] 자바 JVM 메모리 구조 (1) | 2024.12.28 |
[Java] 자바 배열 (0) | 2024.12.27 |
[Java] 자바 반복문 for, while, do while (0) | 2024.12.27 |