자바 메서드 마스터하기: 생성, 호출, 추상화
자바 메서드는 특정 연산을 수행하기 위해 함께 그룹화된 문장들의 모음입니다. 예를 들어 System.out.println() 메서드를 호출하면 시스템은 콘솔에 메시지를 표시하기 위해 여러 문장을 순서대로 실행합니다.
이제 반환 값이 있는 메서드와 없는 메서드를 생성하고, 매개변수가 있는 메서드와 없는 메서드를 호출하며, 프로그램 설계에 메서드 추상화를 적용하는 방법을 배워보겠습니다.
메서드 생성하기
메서드 구문을 설명하기 위해 다음 예제를 살펴보겠습니다.
구문
public static int methodName(int a, int b) {
// body
}
여기서,
- public static - 수정자(modifier)
- int - 반환 타입
- methodName - 메서드 이름
- a, b - 형식 매개변수(formal parameters)
- int a, int b - 매개변수 리스트
메서드 정의는 메서드 헤더와 메서드 본문으로 구성됩니다.
구문
modifier returnType nameOfMethod(Parameter List) {
// method body
}
위 구문에는 다음이 포함됩니다.
- modifier - 메서드의 접근 타입을 정의하며 선택 사항입니다.
- returnType - 메서드는 값을 반환할 수 있습니다.
- nameOfMethod - 메서드 이름입니다. 메서드 시그니처는 메서드 이름과 매개변수 리스트로 구성됩니다.
- Parameter List - 매개변수 리스트로, 메서드의 타입, 순서, 개수를 나타냅니다. 선택 사항이며 매개변수가 없을 수도 있습니다.
- method body - 메서드가 문장들을 통해 수행하는 작업을 정의합니다.
예제: 두 숫자 중 최솟값 구하기
/** 두 숫자 중 최솟값을 반환 */
public static int minFunction(int n1, int n2) {
int min;
if (n1 > n2)
min = n2;
else
min = n1;
return min;
}
메서드 호출하기
메서드를 사용하려면 호출해야 합니다. 메서드 호출에는 값을 반환하는 경우와 반환하지 않는 경우(void) 두 가지가 있습니다.
메서드 호출 과정은 간단합니다. 프로그램이 메서드를 호출하면 프로그램 제어권이 호출된 메서드로 넘어갑니다. 이 메서드는 다음 두 조건에서 호출자에게 제어권을 반환합니다.
return 문이 실행될 때
- 메서드 끝의 닫는 중괄호에 도달할 때
void를 반환하는 메서드는 문장 호출로 간주됩니다. 예:
System.out.println("This is tutorialspoint.com!");
값을 반환하는 메서드는 다음과 같이 이해하면 됩니다.
int result = sum(6, 9);
메서드 정의와 호출 예제
public class ExampleMinNumber {
public static void main(String[] args) {
int a = 11;
int b = 6;
int c = minFunction(a, b);
System.out.println("Minimum Value = " + c);
}
/** 두 숫자 중 최솟값 반환 */
public static int minFunction(int n1, int n2) {
int min;
if (n1 > n2)
min = n2;
else
min = n1;
return min;
}
}
실행 결과
Minimum value = 6
void 키워드
void 키워드는 값을 반환하지 않는 메서드를 생성할 수 있게 해줍니다. 다음 예제에서 methodRankPoints는 void 메서드로, 아무 값도 반환하지 않습니다. void 메서드 호출은 문장이어야 합니다. 즉, methodRankPoints(255.7);처럼 세미콜론으로 끝나야 합니다.
public class ExampleVoid {
public static void main(String[] args) {
methodRankPoints(255.7);
}
public static void methodRankPoints(double points) {
if (points >= 202.5) {
System.out.println("Rank:A1");
} else if (points >= 122.4) {
System.out.println("Rank:A2");
} else {
System.out.println("Rank:A3");
}
}
}
실행 결과
Rank:A1
값에 의한 매개변수 전달(Passing Parameters by Value)
호출 과정에서 인수를 전달해야 합니다. 이들은 메서드 명세의 각 매개변수와 같은 순서여야 합니다. 매개변수는 값에 의해 전달되거나 참조에 의해 전달될 수 있습니다.
값에 의한 전달이란 메서드를 매개변수와 함께 호출하는 것을 의미합니다. 이를 통해 인수 값이 매개변수로 전달됩니다.
예제: 값에 의한 전달
다음 프로그램은 값에 의한 매개변수 전달 예제를 보여줍니다. 인수 값은 메서드 호출 후에도 동일하게 유지됩니다.
public class SwappingExample {
public static void main(String[] args) {
int a = 30;
int b = 45;
System.out.println("Before swapping, a = " + a + " and b = " + b);
// swap 메서드 호출
swapFunction(a, b);
System.out.println("\n**Now, Before and After swapping values will be same here**:");
System.out.println("After swapping, a = " + a + " and b is " + b);
}
public static void swapFunction(int a, int b) {
System.out.println("Before swapping(Inside), a = " + a + " b = " + b);
// n1과 n2 교환
int c = a;
a = b;
b = c;
System.out.println("After swapping(Inside), a = " + a + " b = " + b);
}
}
실행 결과
Before swapping, a = 30 and b = 45
Before swapping(Inside), a = 30 b = 45
After swapping(Inside), a = 45 b = 30
**Now, Before and After swapping values will be same here**:
After swapping, a = 30 and b is 45
메서드 내부에서 값이 바뀌어도 원본 변수에는 영향을 주지 않음을 확인할 수 있습니다.
메서드 오버로딩(Method Overloading)
한 클래스에 같은 이름의 메서드가 두 개 이상 있고 매개변수가 다른 경우를 메서드 오버로딩이라고 합니다. 이는 오버라이딩(overriding)과 다릅니다. 오버라이딩에서는 메서드 이름, 타입, 매개변수 개수 등이 모두 같습니다.
앞서 본 정수 타입의 최솟값 찾기 예제에서, 만약 double 타입의 최솟값을 찾고 싶다면 오버로딩 개념을 도입해 같은 이름의 메서드를 매개변수만 다르게 하여 두 개 이상 만들 수 있습니다.
예제: 오버로딩
public class ExampleOverloading {
public static void main(String[] args) {
int a = 11;
int b = 6;
double c = 7.3;
double d = 9.4;
int result1 = minFunction(a, b); // int 버전 호출
double result2 = minFunction(c, d); // double 버전 호출
System.out.println("Minimum Value = " + result1);
System.out.println("Minimum Value = " + result2);
}
// int 버전
public static int minFunction(int n1, int n2) {
int min;
if (n1 > n2) min = n2;
else min = n1;
return min;
}
// double 버전
public static double minFunction(double n1, double n2) {
double min;
if (n1 > n2) min = n2;
else min = n1;
return min;
}
}
실행 결과
Minimum Value = 6
Minimum Value = 7.3
오버로딩은 프로그램 가독성을 높여줍니다. 같은 이름의 메서드로 int와 double 타입 각각의 최솟값을 구할 수 있습니다.
명령줄 인수 사용하기
프로그램 실행 시 정보를 전달하고 싶을 때가 있습니다. 이는 main()에 명령줄 인수를 전달하여 수행합니다.
명령줄 인수는 프로그램이 실행될 때 프로그램 이름 바로 뒤에 오는 정보입니다. 자바 프로그램 내부에서 명령줄 인수에 접근하는 것은 쉽습니다. 이들은 main()에 전달되는 String 배열에 문자열로 저장됩니다.
예제: 명령줄 인수 출력
public class CommandLine {
public static void main(String args[]) {
for (int i = 0; i < args.length; i++) {
System.out.println("args[" + i + "]: " + args[i]);
}
}
}
다음과 같이 실행해 보세요.
$ java CommandLine this is a command line 200 -100
실행 결과
args[0]: this
args[1]: is
args[2]: a
args[3]: command
args[4]: line
args[5]: 200
args[6]: -100
this 키워드
this는 자바에서 현재 클래스 객체에 대한 참조로, 인스턴스 메서드나 생성자 내에서 사용됩니다. this를 사용하여 생성자, 변수, 메서드 등 클래스 멤버를 참조할 수 있습니다.
주의 - this 키워드는 인스턴스 메서드나 생성자 내에서만 사용 가능합니다.
일반적으로 this 키워드는 다음 용도로 사용됩니다.
- 생성자나 메서드 내에서 인스턴스 변수와 지역 변수 이름이 같을 때 이들을 구별하기 위해
class Student {
int age;
Student(int age) {
this.age = age;
}
}
- 한 클래스 내에서 한 타입의 생성자(매개변수 있는 생성자 또는 기본 생성자)를 다른 생성자에서 호출하기 위해. 이를 명시적 생성자 호출이라고 합니다.
class Student {
int age;
Student() {
this(20);
}
Student(int age) {
this.age = age;
}
}
예제: this 키워드로 클래스 멤버 접근
public class This_Example {
// 인스턴스 변수 num
int num = 10;
This_Example() {
System.out.println("This is an example program on keyword this");
}
This_Example(int num) {
// 기본 생성자 호출
this();
// 지역 변수 num을 인스턴스 변수 num에 할당
this.num = num;
}
public void greet() {
System.out.println("Hi Welcome to Tutorialspoint");
}
public void print() {
// 지역 변수 num
int num = 20;
// 지역 변수 출력
System.out.println("value of local variable num is : " + num);
// 인스턴스 변수 출력
System.out.println("value of instance variable num is : " + this.num);
// 클래스의 greet 메서드 호출
this.greet();
}
public static void main(String[] args) {
// 클래스 인스턴스화
This_Example obj1 = new This_Example();
// print 메서드 호출
obj1.print();
// 매개변수 있는 생성자를 통해 num 변수에 새 값 전달
This_Example obj2 = new This_Example(30);
// print 메서드 다시 호출
obj2.print();
}
}
실행 결과
This is an example program on keyword this
value of local variable num is : 20
value of instance variable num is : 10
Hi Welcome to Tutorialspoint
This is an example program on keyword this
value of local variable num is : 20
value of instance variable num is : 30
Hi Welcome to Tutorialspoint
가변 인자(var-args)
JDK 1.5부터 같은 타입의 가변 개수 인수를 메서드에 전달할 수 있습니다. 메서드 선언에서 매개변수는 다음과 같이 선언합니다.
typeName... parameterName
메서드 선언에서 타입 뒤에 줄임표(...)를 붙입니다. 메서드에는 하나만 가변 길이 매개변수를 지정할 수 있으며, 이는 마지막 매개변수여야 합니다. 일반 매개변수는 이보다 앞에 와야 합니다.
예제: 가변 인자
public class VarargsDemo {
public static void main(String args[]) {
// 가변 인자로 메서드 호출
printMax(34, 3, 3, 2, 56.5);
printMax(new double[]{1, 2, 3});
}
public static void printMax(double... numbers) {
if (numbers.length == 0) {
System.out.println("No argument passed");
return;
}
double result = numbers[0];
for (int i = 1; i < numbers.length; i++)
if (numbers[i] > result)
result = numbers[i];
System.out.println("The max value is " + result);
}
}
실행 결과
The max value is 56.5
The max value is 3.0
finalize() 메서드
객체가 가비지 컬렉터에 의해 최종 소멸되기 직전에 호출될 메서드를 정의할 수 있습니다. 이 메서드를 finalize()라고 하며, 객체가 깨끗하게 종료되도록 보장하는 데 사용할 수 있습니다.
예를 들어, 해당 객체가 소유한 열린 파일을 닫는 데 finalize()를 사용할 수 있습니다.
클래스에 파이널라이저를 추가하려면 단순히 finalize() 메서드를 정의하면 됩니다. 자바 런타임은 해당 클래스의 객체를 재활용하려 할 때마다 이 메서드를 호출합니다.
finalize() 메서드 내부에서는 객체가 소멸되기 전에 수행해야 할 작업을 지정합니다.
finalize() 메서드의 일반적인 형태는 다음과 같습니다.
protected void finalize() {
// finalization code here
}
여기서 protected 지정자는 클래스 외부에서 정의된 코드가 finalize()에 접근하는 것을 방지합니다.
이는 finalize()가 언제 실행될지, 심지어 실행될지조차 알 수 없음을 의미합니다. 예를 들어, 프로그램이 가비지 컬렉션 발생 전에 종료되면 finalize()는 실행되지 않습니다.