[TIL] JAVA - 변수와 메서드 II
💡Day 06 변수와 메서드 II
이 글은 남궁성님의 자바의 정석 3/e를 기반으로 공부한 내용을 정리한 글입니다.
✏️기본형 매개변수와 참조형 매개변수
기본형 매개변수 변수의 값을 읽기만 할 수 있다. (read only)
참조형 매개변수 변수의 값을 읽고 변경할 수 있다. (read & write)
class PrimitiveParamEx {
public static void main(String[] args) {
Data d = new Data(); // 인스턴스 생성
d.x = 10; // d.x에 10값 저장
System.out.println("main() : x = " + d.x);
change(d.x);
System.out.println("After change(d.x)");
System.out.println("main() : x = " + d.x);
}
static void change(int x) {
x = 1000;
System.out.println("change() : x = " + x);
}
}
실행결과
main() : x = 10
change() : x = 1000
After chage(d.x)
main() : x = 10
문제점
change메서드에서 main메서드로부터 넘겨받은 d.x의 값을 1000으로 변경했는데도 main메서드에서는 d.x의 값이 그대로다.
- d.x의 값이 변경된 것이 아니라, change메서드의 매개변수 x의 값이 변경됐기 때문이다.
class Data { int x; }
class ReferenceParamEx {
public static void main(String[] args) {
Data d = new Data();
d.x = 10;
System.out.println("main() : x = " + d.x);
change(d);
System.out.println("After chanage(d)");
System.out.println("main() : x = " + d.x);
}
static void change(Data d){
//매개변수가 첨조형이기 때문에 x의 값이 아닌 주소가 매개변수 d에 복사되었다.
d.x = 1000;
// main메서드의 참조변수 d와 change메서드의 참조변수 d는 같은 객체를 가리킨다.
System.out.println("change() : x = " + d.x);
}
}
실행결과
main() : x = 10
change() : x = 1000
After change(d)
main() : x = 1000
참조형 매개변수
값이 아닌 '값이 저장된 주소'를 넘겨주면 값을 읽어오는 것뿐만 아니라 변경하는 것도 가능하다.
class ReferenceOaranEx2 {
public static void main(String[] args) {
int[] x = {10}; // 크기가 1인 배열. x[0] = 10;
System.out.println("main() : x = " + x[0]);
change(x);
System.out.println("After change(x)");
System.out.println("main() : x = " + x[0]);
}
static void change(int[] x) {
x[0] = 1000;
System.out.println("change() : x = " + x[0]);
}
}
실행결과
main() : x = 10
change() : x = 1000
After change(x)
main() : x = 1000
배열도 객체와 같이 참조변수를 통해 데이터가 저장된 공간에 접근하기 때문에 참조형 매개변수와 같은 결과를 얻을 수 있다.
임시적으로 간단히 처리할 때는 별도의 클래스를 선언하는 것보다 이처럼 배열을 이용할 수도 있다.
✏️참조형 반환타입
매개변수뿐만 아니라 반환타입도 참조형이 될 수 있다.
반환타입이 참조형이라는 것은 메서드가 '객체의 주소'를 반환한다는 것을 의미한다.
✏️재귀호출(recursive call)
메서드의 내부에서 메서드 자신을 다시 호출하는 것을 '재귀호출'이라 한다.
void method() {
method(); // 재귀호출. 메서드 자신을 호출한다.
}
조건문과 함께
오로지 코드가 재귀호출 뿐이라면, 무한반복에 빠지게 된다. 무한반복부이 조건문과 함께 사용되어야하는 것처럼, 재귀호출도 조건문이 필수적으로 따라다닌다.
void method(int n) {
if(n == 0)
return; // n의 값이 0일 때, 메서드를 종료한다.
System.out.println(n);
method(--n); // 재귀호출. method(int n)을 호출
}
재귀호출과 반복문
재귀호출은 반복문과 유사한 점이 많으며, 대부분의 재귀호출은 반복문으로 작성하는 것이 가능하다.
반복문보다 재귀호출의 수행시간이 더 오래 걸린다.
- 왜 굳이 반복문대신 재귀호출을 사용할까?
논리적 간결함 때문
대표적인 재귀호출의 예시 팩토리얼(factorial)
f(n) = n * f(n-1), 단 f(1) = 1
class FactorialTest {
public static void main(String args[]) {
int result = factorial(4);
System.out.println(result);
}
static int factorial(int n) {
int result = 0;
if(n == 1)
result = 1;
else
result = n * factorial(n-1); // 다시 메서드 자신을 호출한다.
return result;
}
}
만일 factorial메서드의 매개변수 n의 값이 0이면??
'호출하는 사람이 당연히 알아서 적절한 값을 인자로 주겠지.' 라는 막연한 믿음을 가져서는 안 된다. 매개변수의 유효성검사는 중요하다.
✏️클래스 메서드(static메서드)와 인스턴스 메서드
인스턴스 메서드는 인스턴스 변수와 관련된 작업을 하는, 즉 메서드의 작업을 수행하는데 인스턴스 변수를 필요로 하는 메서드이다.
반면에 메서드 중에서 인스턴스와 관계없는(인스턴스 변수나 인스턴스 메서드를 사용하지 않는) 메서드를 클래스 메서드(static메서드)로 정의한다.
어떤 경우에 인스턴스 메서드, 클래스 메서드를 사용해야 할까?
-
클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에 static을 붙인다.
모든 인스턴스에서 같은 값이 유지되어야 하는 변수는 static을 붙여서 클래스변수로 정의해야 한다.
-
클래스 변수는 인스턴스를 생성하지 않아도 사용할 수 있다.
-
클래스 메서드(static메서드)는 인스턴스 변수를 사용할 수 없다.
클래스 메서드가 호출되었을 때 인스턴스가 존재하지 않을 수도 있다.
-
메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려한다.
메서드 호출시간이 짧아지므로 성능이 향상된다.
고려사항
-
클래스의 멤버변수 중 모든 인스턴스에 공통된 값을 유지해야하는 것이 있는지 살펴보고 있으면, static을 붙여준다.
-
작성한 메서드 중에서 인스턴스 변수나 인스턴스 메서드를 사용하지 않는 메서드에 static을 붙일 것을 고려한다.
-
클래스안에 멤버변수를 사용하지 않는 메서드(매개변수만 받는 메서드)에는 static을 붙일 것을 고려한다.
예제를 통해 어떤 경우 인스턴스메서드로, 또는 클래스메서드로 선언해야하는지 확인
class MyMath2 {
long a, b;
// 인스턴스변수 a, b만을 이용해서 작업하므로 매개변수가 필요없다.
long add() { return a + b; }
long subtract() { return a - b; }
long multiply() { return a * b; }
double divide() { return a / b; }
// 인스턴스변수와 관계없이 매개변수만으로 작업이 가능하다.
static long add(long a, long b) { return a + b; }
static long subtract(long a, long b) { return a - b; }
static long multiply(long a, long b) { return a * b; }
static double divide(double a, double b) { return a / b; }
}
public class MyMathTest2 {
public static void main(String[] args) {
// 클래스메서드 호출, 인스턴스 생성없이 호출가능
System.out.println(MyMath2.add(200L, 100L));
System.out.println(MyMath2.subtract(200L, 100L));
System.out.println(MyMath2.multiply(200L, 100L));
System.out.println(MyMath2.dvide(200.0, 100.0));
MyMath2 mm = new MyMath2(); // 인스턴스를 생성
mm.a = 200L;
mm.b = 100L;
// 인스턴스메서드는 객체생성 후에만 호출이 가능함
System.out.println(mm.add());
System.out.println(mm.subtract());
System.out.println(mm.multiply());
System.out.println(mm.divide());
}
}
실행결과
300
100
20000
2.0
300
100
20000
2.0
Author And Source
이 문제에 관하여([TIL] JAVA - 변수와 메서드 II), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@qudalsrnt3x/TIL-JAVA-변수와-메서드-II저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)