이 글을 쓰게된 이유는 자바에 대해 처음부터 제대로 공부하기 위해 김영한님 자바 강의를 듣고 있는 중이다.
자바 강의를 들으면서, 함수 정의에 대한 부분이 나왔고, 학부 시절에 C++ 강의를 들을 때 배웠던 swap 함수가 생각이 났다. 그래서 단순히 'JAVA에서는 swap을 어떻게 구현할까?'라는 생각이 들었다.
C++에서는 참조형 변수를 받아서, 파이썬에서는 그냥 변수를 바꿔 대입해주면 된다.
자바는 그럼 어떻게 구현할 수 있을까?
🔍 자바에서는 SWAP을 어떻게 구현할까?
자바에서는 항상 변수의 값을 복사에서 대입한다.
위 내용을 명시하자.
자바에서 변수에 값을 대입하는 것은 변수에 들어 있는 값을 복사해서 대입하는 것이다.
기본형이면 변수에 들어 있는 실제 사용하는 값을 복사 해서 대입하고, 참조형이면 변수에 들어 있는 참조값을 복사해서 대입한다.
▶️ 기본형에서의 메서드 호출
아래 예제와 같이 메서드 내에서 x의 값을 바뀐다고 해서 main 함수에서의 x 값이 바뀌는 게 아니다.
changePrimitive 함수의 parameter x는 단순히 main 함수의 x 값을 복사해 대입해준 것이기 때문이다.
public class MethodChange1 {
public static void main(String[] args) {
int a = 10;
System.out.println("메서드 호출 전: a = " + a);
changePrimitive(a);
System.out.println("메서드 호출 후: a = " + a);
}
static void changePrimitive(int x) {
x = 20;
}
}
▶️ 참조형에서의 메서드 호출
참조형의 경우에는 어떻게 될까?
먼저 참조형의 경우 changeReference 함수에서 parameter로 Data 클래스를 받아온다. 이때 main 함수에서는 Data 인스턴스를 argument로 넘겨주게 된다.
그러면 참조형의 경우에는 변수의 참조값을 복사해서 함수의 parameter로 넘겨주게 된다.
따라서 아래의 예제에서는 argument로 넘긴 dataA 인스턴스의 참조값으로 value를 직접 접근하여 20으로 바꿀 수 있다.
public class MethodChange2 {
public static void main(String[] args) {
Data dataA = new Data();
dataA.value = 10;
System.out.println("메서드 호출 전: dataA.value = " + dataA.value);
changeReference(dataA);
System.out.println("메서드 호출 후: dataA.value = " + dataA.value);
}
static void changeReference(Data dataX) {
dataX.value = 20;
}
}
즉, 함수에서 어떤 값을 직접 바꾸기 위해선 참조형 변수가 필요한 것이다.
이 아이디어로 swap 함수를 구현할 수 있다.
🔑 참조형 변수로 swap 함수 구현하기
위 설명을 통해, 함수 내에서 main 함수의 변수 값을 직접 변경하기 위해서는 참조형 변수를 이용해야 된다는 것을 알 수 있었다.
그럼 참조형 변수를 통해 swap을 구현해보자!
참조형 변수에는 클래스와 배열 등이 있지만, 이번 글에서는 클래스로만 구현을 할 것이다.
아래와 같이 swap 할 멤버변수를 포함하는 클래스를 정의해서, swap 메서드에서 해당 클래스의 인스턴스를 받아와 값을 바꿔주면 된다. 그러면 참조형의 주소값을 불러와 직접 값을 변경하기 때문에 값이 잘 바뀐다!
class IntWrapper {
int value;
IntWrapper(int value) {
this.value = value;
}
}
public class SwapExample {
public static void swap(IntWrapper a, IntWrapper b) {
int temp = a.value;
a.value = b.value;
b.value = temp;
}
public static void main(String[] args) {
IntWrapper a = new IntWrapper(1);
IntWrapper b = new IntWrapper(2);
System.out.println("Before swap: a = " + a.value + ", b = " + b.value);
swap(a, b);
System.out.println("After swap: a = " + a.value + ", b = " + b.value);
}
}
추가로 자바에는 Call by Reference의 개념이 없다고 한다.
C와 달리 자바에서는 포인터를 철저하게 숨겨 개발자가 직접 메모리 주소에 접근하지 못하게 조치했기 때문이라고 한다.
C언어에서는 포인터를 통해 그대로 주소를 받아 메모리를 참조할 수 있는데, C와 달리 자바에서는 지원하지 않는다. 위와 같은 이유 때문인 거 같다.
'Java' 카테고리의 다른 글
[JAVA] main() 메서드는 정적 메서드이다! (0) | 2024.07.05 |
---|---|
[JAVA] 자바의 메모리 구조에 대해 알아보자 (0) | 2024.07.03 |
[JAVA] 자바 컴파일과 실행 과정에 대해 알아보자 (0) | 2024.07.02 |
[JAVA] compareTo()에 대해 알아보자(문자열, 숫자 비교) (1) | 2024.04.18 |
[Java] 이미지 리사이징을 통해 이미지 로딩 속도를 개선하자. (0) | 2023.10.20 |