참조형 매개변수, 참조형 반환타입
참조형 매개변수
- 기본형 매개변수 - 변수의 값을 읽기만 할 수 있다. (read only)
- 참조형 매개변수 - 변수의 값을 읽고 변경할 수 있다. (read & write)
[Ex6_7]
class Data2 {int x;}
public class Ex6_7 {
public static void main(String[] args) {
Data2 d = new Data2(); // Data2 객체 생성
d.x = 10; // Data2클래스 객체 d의 x에 10을 저장
System.out.println("main() : x = " + d.x); // Data2클래스 객체 d에 저장되어 있는 x값 10출력
change(d); // change 메서드 호출
System.out.println("After change(d)");
System.out.println("main() : x = " + d.x);
}
static void change(Data2 d) {// 참조형 매개변수
d.x = 1000;
System.out.println("change() : x = " + d.x);
}
}
[실행 결과]
main() : x = 10
change() : x = 1000
After change(d)
main() : x = 1000
프로그램을 실행시키면 스택에 메인메서드가 올라간다.
메인메서드의 첫 줄을 실행하면 d가 만들어지고, Data2객체가 만들어진다. Data2객체의 멤버는 x이다. 이 x는 int이므로 생성되었을 때, 0으로 자동초기화 된다. 그리고 이 객체의 주소가 메인메서드의 변수 d에 저장된다.
그다음, 참조변수 d가 가리키는 객체의 x값에 10을 저장한다.
그리고, d.x값은 10이므로 println메서드가 스택에 호출되서 올라간다음, 10을 출력한다.
그다음, 다시 println 메서드가 종료되면서 다시 메인메서드가 활성화된다.
그리고, change메서드를 호출하면 호출스택에 change메서드가 올라가서 실행상태가 되고, main메서드는 다시 대기상태가 된다
change메서드의 파라미터는 기본형이 아니라 참조형이다.
참조형 매개변수 d로메인메서드의 d값(d객체의 주소)이 복사가 된다.
그러면, change메서드의 참조변수도 Data2객체의 주소를 가지고 있으므로, 해당객체를 가치키게 된다.
그러면, d.x = 1000; 이 실행되면, 참조변수 d가 가리키고 있는 x에 저장한다.
이때 d는, change의 지역변수 d를 의미한다.
change의 지역변수 d가 가리키는 주소에 있는 x값을 1000으로 바꾼다.
그리고 println메서드를 호출하면 스택에 println메서드가 올라가고, 이때 출력할 d.x의 값은 1000이 된다.
println메서드가 실행되고, 1000이 출력된다.
그리고 다시 println메서드는 제거되고 다시 chnage메서드로 돌아온다.
그리고, change메서드로 다시 돌아왔는데, 더이상 실행할 문장이 없으므로,
change메서드가 종료된다. 그래서 다시 change메서드를 호출했던 곳으로 돌아간다.
그러면 스택에는 main메서드가 활성화 되게 된다.
그다음 println이 호출되면서 각 문장이 출력되는데, 이때 d.x값은 d가 가리키는 객체의 x값이 1000이므로 1000을 출력한다.
그리고나면, main메서드에도 더이상 실행할 문장이 없으므로, main메서드도 종료가되고, 스택은 완전히 비워지면서 프로그램이 종료된다.
change메서드의 매개변수(파라미터)가 기본형타입 이었을 경우에는,
메서드 내에서 x값을 바꿧는데도, main메서드의 x값은 바뀌지 않았다.
그러나, 이번 예시처럼 change메서드의 매개변수(파라미터)가 참조형타입인 경우에는,
change메서드 내에서 x값을 바꿔서 저장했는데,
main메서드의 x값도 바뀌어 저장된 것을 확인 할 수 있었다.
이처럼, 메서드한테 참조형 매개변수를 통해서 객체의 주소를 전달해 주면,
해당 메서드는, 전달받은 주소가 가리키는 객체에 직접 다룰 수 있게 된다.
참조변수를 통해 객체를 직접 다룰 수 있다는 것은, 객체에 있는 값을 읽어올 수도 있고, 쓸수도 있다.(변경이 가능)
참조변수로 객체의 주소를 가지고 있기 때문에..
- 기본형 매개변수 - 변수의 값을 읽기만 할 수 있다. (read only)
- 참조형 매개변수 - 변수의 값을 읽고 변경할 수 있다. (read & write)
참조형 매개변수가 변수의 값을 읽고 변경할 수 있는 read & write의 기능을 할 수 있다는 것을 이해할 수 있다.
참조형 반환 타입
이번에는 반환타입이 참조형이 경우이다. 반환타입이 기본형이 경우는 대부분 잘 이해한다.
그런데, 반환타입이 참조형인 경우를 어려워 하는 경우가 있다. 그림을 통해 알아보자.
[Ex6_8]
class Data3 {int x;}
public class Ex6_8 {
public static void main(String[] args){
Data3 d = new Data3();
d.x = 10;
Data3 d2 = copy(d);
System.out.println("d.x ="+d.x);
System.out.println("d2.x="+d2.x);
}
static Data3 copy(Data3 d) {
Data3 tmp = new Data3(); // 새로운 객체 tmp를 생성한다.
tmp.x = d.x; // d.x의 값을 tmp.x에 복사한다.
return tmp; // 복사한 객체의 주소를 반환한다.
}
}
[실행 결과]
d.x =10
d2.x=10
이 프로그램을 실행하는 과정을 그림으로 표현하면 아래와 같다.
처음에 스택에 main메서드가 올라가면서 프로그램이 시작된다.
참조변수 d가 만들어지고, Data3객체가 만들어진다. Data3객체의 멤버는 x 1개이다. 그래서 x가 만들어는데, int형이므로 0으로 초기화된다. 그리고 만들어진 Data3 객체의 주소가 d에 저장된다. 그러면 참조변수 d와 Data3객체가 연결이 된다.
그다음에, d.x에 10을 저장한다. 즉, d가 가리키는 객체의 x값에 10을 저장한다.
그리고 main메서드에 Data3타입의 참조변수 d2가 선언되고, copy메서드가 호출된다.
그러면, main메서드가 대기상태가 되고, copy메서드가 실행이 되는데, copy메서드로 d값을 복사해준다.
즉, Data3타입의 참조형 d가 생성된다. 이 d는 copy메서드의 lv(지역변수)이다.
copy메서드의 지역변수 d에 메인메서드 Data3 d를 복사한다.
결국, copy메서드의 지역변수 Data3 d도 메인메서드의 지역변수 d에서 생성한 객체를 가르키는 주소를 저장하게 된다.
즉, copy메서드의 참조변수d도 메인메서드의 d가 가리키는 Data3객체를 가리키게 된다.
이 상태에서, copy메서드에 변수 tmp를 만들고, 새로운 Data3객체를 생성해서 그 주소를 tmp에 저장한다.
참조변수 tmp가 새로만든 Data3객체를 가리키게 된다.
그 다음에, copy의 지역변수 d가 가리키는 x값 10을 tmp.x에 저장한다.
그다음, return tmp인데, tmp값은 주소 0x200이다.(예시 주소임)
copy메서드의 반환타입은 참조형인데,
메서드의 반환타입이 참조형일 경우에는 객체의 주소를 반환한다.
그리고 해당 객체의 주소가 Data3 d2에 저장된다.
d2는 메인메서드의 지역변수이고, 메인메서드의 지역변수 d2는 copy메서드에서 새로 만들어진 객체의 주소를 가리키게 된다.
근데, copy메서드가 종료되는 순간, copy메서드에 있던 지역 변수들도 다 제거된다.
그 다음에, println메서드가 호출되어 d가 가리키는 객체의 x값인 10(그림에서 주소값 0x100인 객체의 x값) 이 출력되고 메서드가 종료되고, 그다음 줄 print메서드가 호출되어 d2가 가리키는 객체의 x값인 10(그림에서 주소값 0x200인 객체의 x값)이 출력되게 된다.
즉, 반환타입이 참조형이면,
"객체의 주소를 반환한다" (객체를 반환한다고 생각해도 된다.)
해당 메서드의 반환 타입과, 해당 메서드의 return을 저장할 변수의 타입이 일치해야 한다.
추가로,
같은 클래스에 있는 메서드는 참조변수를 생략하고 호출하는 것이 가능하다.
그리고 static메서드는 객체의 생성없이 호출이 가능하다
원래 정석은,
Ex6_8 e = new Ex6_8(); // 객체 생성
e.copy(); 호출
요렇게 하는게 정석이다.
다음 시간에 자세히 공부할 테니, 이렇구나 하고 알아두기만 하고 넘어가도 좋다.
'JAVA' 카테고리의 다른 글
오버로딩 (1) | 2022.03.28 |
---|---|
static메서드와 인스턴스 메서드 (0) | 2022.03.28 |
기본형매개변수 (0) | 2022.03.26 |
호출 스택 (call stack) (0) | 2022.03.26 |
return문, 반환값 (0) | 2022.03.26 |
댓글
이 글 공유하기
다른 글
-
오버로딩
오버로딩
2022.03.28 -
static메서드와 인스턴스 메서드
static메서드와 인스턴스 메서드
2022.03.28 -
기본형매개변수
기본형매개변수
2022.03.26 -
호출 스택 (call stack)
호출 스택 (call stack)
2022.03.26