메서드 또는 생성자에 정보 전달하기
메서드 또는 생성자에 대한 선언은 해당 메서드 또는 생성자에 대한 인수의 수와 타입을 선언합니다. 예를 들어 다음은 대출 금액, 이자율, 대출 기간(기간 수), 대출의 미래 가치에 따라 주택 대출의 월별 페이먼트를 계산하는 메서드입니다:
public double computePayment(
double loanAmt,
double rate,
double futureValue,
int numPeriods) {
double interest = rate / 100.0;
double partial1 = Math.pow((1 + interest),
- numPeriods);
double denominator = (1 - partial1) / interest;
double answer = (-loanAmt / denominator)
- ((futureValue * partial1) / denominator);
return answer;
}이 방법에는 대출 금액, 이자율, 미래 가치, 기간의 네 가지 매개변수가 있습니다. 처음 세 개는 배정밀도 부동 소수점 숫자이고, 네 번째는 정수입니다. 매개변수는 메서드 본문에서 사용되며 런타임에 전달된 인수의 값을 취합니다.
참고: 매개변수 는 메서드 선언의 변수 목록을 나타냅니다. 인수는 메서드가 호출될 때 전달되는 실제 값입니다. 메서드를 호출할 때 사용되는 인수는 선언의 매개변수와 타입 및 순서가 일치해야 합니다.
매개변수 타입
메서드나 생성자의 매개변수에는 모든 데이터 타입을 사용할 수 있습니다. 여기에는 computePayment() 메서드에서 본 것처럼 이중, 실수, 정수와 같은 기본 데이터 타입과 객체 및 배열과 같은 참조 데이터 타입이 포함됩니다.
다음은 배열을 인수로 받는 메서드의 예입니다. 이 예제에서 이 메서드는 새로운 Polygon 객체를 생성하고 Point 객체의 배열로부터 초기화합니다(Point는 x, y 좌표를 나타내는 클래스라고 가정합니다):
public Polygon polygonFrom(Point[] corners) {
// method body goes here
}
임의의 인자 수
varargs 라는 구문을 사용하여 메서드에 임의의 수의 값을 전달할 수 있습니다. 특정 타입의 인수가 메서드에 몇 개나 전달될지 모를 때 varargs를 사용합니다. 이는 배열을 수동으로 생성하는 지름길입니다(이전 방법에서는 배열 대신 varargs를 사용했을 수도 있습니다).
varargs를 사용하려면 마지막 매개변수의 타입 뒤에 줄임표(점 3개, …), 공백, 매개변수 이름을 붙이면 됩니다. 그런 다음 매개 변수가 없더라도 해당 매개 변수의 수에 관계없이 메서드를 호출할 수 있습니다.
public Polygon polygonFrom(Point... corners) {
int numberOfSides = corners.length;
double squareOfSide1, lengthOfSide1;
squareOfSide1 = (corners[1].x - corners[0].x)
* (corners[1].x - corners[0].x)
+ (corners[1].y - corners[0].y)
* (corners[1].y - corners[0].y);
lengthOfSide1 = Math.sqrt(squareOfSide1);
// more method body code follows that creates and returns a
// polygon connecting the Points
}메서드 내부에서 corners가 배열처럼 취급되는 것을 볼 수 있습니다. 이 메서드는 배열 또는 인수의 시퀀스를 사용하여 호출할 수 있습니다. 메서드 본문의 코드는 두 경우 모두 매개변수를 배열로 취급합니다.
인쇄 메서드에서 가장 흔히 볼 수 있는 변수는 printf() 메서드입니다:
public PrintStream printf(String format, Object... args)위 함수를 사용하면 임의의 수의 객체를 인쇄할 수 있습니다. 다음과 같이 호출할 수 있습니다:
System.out.printf("%s: %d, %s%n", name, idnum, address);또는 다음과 같이
System.out.printf("%s: %d, %s, %s, %s%n", name, idnum, address, phone, email);또는 다른 인수를 사용할 수 있습니다.
매개변수 이름
메서드나 생성자에 매개변수를 선언할 때 해당 매개변수의 이름을 지정합니다. 이 이름은 메서드 본문 내에서 전달된 인수를 참조하는 데 사용됩니다.
매개변수의 이름은 해당 범위에서 고유해야 합니다. 동일한 메서드 또는 생성자에 대한 다른 매개변수의 이름과 같을 수 없으며 메서드 또는 생성자 내의 로컬 변수의 이름일 수 없습니다.
매개변수는 클래스의 필드 중 하나와 같은 이름을 가질 수 있습니다. 이 경우 매개변수가 필드를 섀도잉한다고 합니다. 필드를 섀도잉하면 코드를 읽기 어렵게 만들 수 있으며 일반적으로 특정 필드를 설정하는 생성자 및 메서드 내에서만 사용됩니다. 예를 들어 다음 Circle 클래스와 그 setOrigin() 메서드를 생각해 보세요:
public class Circle {
private int x, y, radius;
public void setOrigin(int x, int y) {
...
}
}Circle 클래스에는 세 개의 필드가 있습니다: x, y, radius의 세 가지 필드가 있습니다. setOrigin() 메서드에는 두 개의 매개변수가 있으며, 각 매개변수는 필드 중 하나의 이름과 동일한 이름을 가집니다. 각 메서드 매개변수는 해당 이름을 공유하는 필드를 가리킵니다. 따라서 메서드 본문에서 x 또는 y라는 단순한 이름을 사용하면 필드가 아니라 매개 변수를 가리킵니다. 필드에 액세스하려면 정규화된 이름을 사용해야 합니다. 이에 대해서는 이 단원의 뒷부분에 있는 “this 키워드 사용” 섹션에서 설명합니다.
원시 데이터 타입 인자 전달하기
int 또는 double과 같은 프리미티브 인수는 값으로 메서드에 전달됩니다. 즉, 매개변수 값에 대한 모든 변경 사항은 메서드의 범위 내에서만 존재합니다. 메서드가 반환되면 매개변수는 사라지고 매개변수에 대한 모든 변경 사항이 손실됩니다. 다음은 예시입니다:
public class PassPrimitiveByValue {
public static void main(String[] args) {
int x = 3;
// invoke passMethod() with
// x as argument
passMethod(x);
// print x to see if its
// value has changed
System.out.println("After invoking passMethod, x = " + x);
}
// change parameter in passMethod()
public static void passMethod(int p) {
p = 10;
}
}이 프로그램을 실행하면 출력은 다음과 같습니다:
After invoking passMethod, x = 3
참조 데이터 타입 인수 전달하기
객체와 같은 참조 데이터 타입 매개변수도 값으로 메서드에 전달됩니다. 즉, 메서드가 반환될 때 전달된 참조는 여전히 이전과 동일한 객체를 참조합니다. 그러나 객체의 필드에 적절한 액세스 수준이 있는 경우 메서드에서 필드 값을 변경할 수 있습니다.
예를 들어 임의의 클래스에서 Circle 객체를 이동하는 메서드를 생각해 봅시다:
public void moveCircle(Circle circle, int deltaX, int deltaY) {
// code to move origin of circle to x+deltaX, y+deltaY
circle.setX(circle.getX() + deltaX);
circle.setY(circle.getY() + deltaY);
// code to assign a new reference to circle
circle = new Circle(0, 0);
}이 인수를 사용하여 메서드를 호출할 수 있습니다:
moveCircle(myCircle, 23, 56)메서드 내에서 circle은 처음에 myCircle을 참조합니다. 이 메서드는 원이 참조하는 객체(즉, myCircle)의 x 및 y 좌표를 각각 23과 56씩 변경합니다. 이러한 변경 사항은 메서드가 반환될 때 지속됩니다. 그런 다음 circle은 x = y = 0으로 새로운 Circle 객체에 대한 참조를 할당받습니다. 그러나 참조가 값으로 전달되어 변경할 수 없기 때문에 이 재할당은 영구성이 없습니다. 메서드 내에서 circle이 가리키는 객체는 변경되었지만 메서드가 반환될 때 myCircle은 여전히 메서드가 호출되기 전과 동일한 Circle 객체를 참조합니다.