자바라는 객체 지향 프로그래밍(OOP) 언어를 공부하면서 메소드를 생성하고 Handling하는 연습이 부족한것 같아 이번 게시글에서는 메소드 (Method) 를 생성하고 Handling 하는 예제들을 다루어보면서 이해해보자.
이전에 만들어 두었던 Account 클래스를 가지고 공부해보자
[메소드 연습 예제1]
1. 계좌를 개설하여 계좌에 대한 정보를 가리키는 주소를 변수 src에 저장한다.
2. 주소를 가지고있는 변수 src를 다시 temp 변수에 저장한다.
3. 두 변수 src와 temp는 동일한 주소를 가지고 있는지 확인해본다.
∴ 여기서 우리가 알아야할 점은 주소도 변수를 통해 이동이 가능하다는 점이다.(자바는 객체 지향 프로그래밍 언어이기때문에 주소를 주고
받으면서 유연한 프로그래밍을 할 수 있다는 것을 알아야한다.
1. Account 클래스에 정의된 setPwd() 메소드를 활용하여 변수 temp의 비밀번호를 변경한다.
2. Account 클래스 타입 변수 temp와 src는 같은 주소값을 가지고 있기때문에, 어느 한 곳에서 정보를 변경하면 갱신된 정보를 공유하게된다.
[메소드 연습 예제2]
· 위 문제는 main() 메소드에서 생성한 인스턴스의 정보를 printAccount() 메소드에서 출력하고 싶을 때 어떻게 해야할까?
1. 자바는 객체 지향 프로그래밍 언어이고, 우리는 어떻게 하면 인스턴스 정보를 전달할 수 있을까라는 사고를 먼저하게된다.
2. "객체는 누가 가리키지?" -> "객체를 가리키는 주소는 obj1과 obj2가 가지고있지!!"라는 사고를 해야한다.
3. 주소를 printAccount() 메소드에 넘기려면 우선 main() 메소드에서 메소드를 호출해야한다.
4. 호출부에서 주소를 알고있는 변수 obj1과 obj2를 담아서 전달해야한다.
5. 그래서 printAccount( ? ) 에서 물음표에 들어갈 자료형은 obj1과 obj2의 자료형인 Account 클래스와 동일해야한다.(여기서 주소의 이동이
이루어질때, 주소를 전달하는 변수의 자료형과 주소를 받는 변수의 자료형이 일치해야한다는 사실을 알 수 있다.)
6. 여기서 주소를 전달받을 때 자료형이 중요한것이지 변수명은 아무거나 지정해도 상관은 없다.(다만 주소를 전달받는 매개변수도 남들이 봤을 때,
알아보기 쉬운 변수명이면 더 좋을것이다.)
7. 마지막으로 printf 형식을 사용해서 temp.(점)으로 접근하여 Account 클래스에 정의되어있는 getAccountNumber() 메소드와 getBalance()
메소드를 호출할 수 있다.
[메소드 연습 예제3]
· 위 문제는 main() 메소드에서 int형 1차원 배열 변수 arr에 1, 5, 2, 6, 7이라는 값을 초기화하고 printArray() 메소드에서 for each
(Enhaced for 문)을 사용하여 배열의 요소를 콘솔에 출력해보자.
1. 위의 문제와 동일하다. printArray() 메소드에서 배열의 내용을 어떻게 알 수 있을까?부터 시작한다.
2. 배열의 요소를 가리키는 주소를 전달받으면 배열의 요소를 알 수 있다는 사실을 이제는 알 것이다.
3. 배열의 주소를 전달하기위해 main() 메소드에서 printArray() 메소드를 호출하고 인자값으로 int형 1차원배열 arr을 전달한다.
4. 당연히 전달하는 arr의 자료형이 int형 1차원배열이니 인자값을 전달받을 printArray() 메소드의 매개변수도 자료형이 int형 1차원배열
이어야한다.
5. for each 문의 문법에 따라 주소를 가리키는 매개변수 temp에 들어있는 정보는 자료형이 int형이기때문에 전달받을 변수 temp1의 자료형
은 int형이어야한다.
6. for each 문은 배열의 size만큼 반복되기때문에 printf 형식 출력문을 이용하여 배열의 요소를 출력한다.
[메소드 연습 예제4]
· 이번 문제는 위의 상황과 반대이다. 이번에는 인스턴스 생성을 main() 메소드가 아닌 따로 생성한 메소드에서 하고 출력을
main() 에서 하고싶은 경우이다.
1. 프로그램의 시작은 main() 메소드이다.
2. 인스턴스의 정보를 가리키는 변수 account의 주소를 받아와야한다는 사고를 해야한다.
3. 그리고 주소를 받아온 것을 저장하려면 변수 하나가 더 필요하다.
4. 주소를 저장할 변수 Account 클래스 타입 temp에 메소드를 호출한다.
(호출부에서 메소드로 넘어가서 리턴값을 받아온다.)
5. 인스턴스 정보를 가리키는 주소는 Account 클래스 타입의 변수 account가 가지고 있다.
6. 주소를 전달해야하니 return 이라는 키워드로 변수 account 를 전달해야한다.
7. return 값이 있는 경우 createAccount() 메소드의 리턴유형도 void가 아니라 상황에 맞게 Account 클래스여야한다.
8. 리턴(반환)된 주소는 temp에 저장되고, temp.(점)으로 Account 클래스에 접근하여 계좌번호와, 잔고를 정의된 메소드
를 통해 불러온다.
[메소드 연습 예제5]
· 배열 선언 및 생성
· 배열 요소 할당
· 배열 요소 출력 (for 문) : 계좌번호, 잔고
· 배열 요소 출력 (Enhanced for 문) : 계좌번호, 잔고
1. Account 클래스 1차원배열 변수 accounts에 배열 공간이 5개인 1차원배열을 생성한다.
2. 배열 요소를 할당하기 위해 index로 접근하여 매개변수 생성자에 맞게 계좌번호, 이름, 비밀번호, 잔고
를 입력한 계좌 5개를 생성한다.
3. for 문으로 계좌번호와 잔고를 출력하는데 i는 0부터 배열의 길이인 length 속성을 사용하여 accounts.
length 미만까지 조건을 지정한다.
4. Account 클래스 1차원배열 변수인 accounts의 index를 돌며 Account 클래스에 정의된 getAccount
Number() 메소드와 getBalance() 메소드를 호출한다.
5. 이번에는 for each 문(Enhanced for 문)을 이용하여 1차원배열을 가리키는 주소가 저장된 변수
accounts를 Account 클래스 변수 temp에 전달한다.
6. 이제 똑같이 Account 주소를 저장하고 있는 변수 temp.(점)을 이용하여 Account 클래스에 정의된
getAccountNumber() 메소드와 getBalance() 메소드를 호출하여 배열의 size만큼 반복(루프)을 하며
출력한다.
[메소드 연습 예제6]
· 위 예제와 다른점은 이번에는 createAccounts() 메소드는 static 키워드를 사용하는 클래스 메소드가
아닌 인스턴스 메소드이다.
· 인스턴스 메소드에서 main() 메소드에 정보를 전달하여 for each 문으로 정보를 출력하세요.
1. 프로그램의 시작은 언제나와같이 main() 메소드이다.
2. 인스턴스 메소드에 접근하기위해서는 우선 해당 클래스에 접근해야하기때문에 매개변수가 없는 디폴트
인스턴스를 생성한다.
3. Method7 클래스 타입을 가진 obj.(점)으로 클래스 안에 정의된 createAccounts() 메소드에 접근한다.
4. 메소드를 호출하게되면 Account 1차원배열 변수 accounts는 1차원 배열의 공간이 5개인 인스턴스
공간을 생성했고, 각 인덱스에 생성한 계좌정보를 가리키는 주소가 저장되어있다는 사실을 알아야한다.
5. 다시 main()에서 처음 메소드호출부로 돌아가기위해서는 createAccounts() 메소드 안에서 전달할 값을
return(반환) 해주어야하기때문에 인스턴스 정보를 가지고 있는 Account 클래스 1차원배열 타입 변수
accounts를 전달한다. 당연히 리턴값이 accounts기때문에 리턴유형도 같은 타입인 Account 1차원배열
이어야한다.
6. 리턴값을 메소드호출부로 전달받아 다시 변수 accounts 에 저장한다.(여기서 질문! accounts 변수는
createAccounts() 메소드 안에서 이미 사용을 했는데, main() 메소드 안에서도 사용이 어떻게 가능
할까?라는 의문이 들 수 있다. 정답은 변수 accounts는 메소드안에서 사용한 로컬(지역) 변수이기때문에
동일한 변수이름을 사용할 수 있는것이다.
7. 나머지는 for each 문의 문법에 따라 accounts에 저장된 값을 임시변수 temp에 저장하고 printf 형식
에 따라 계좌번호와 잔고를 출력한다.
[메소드 연습 예제7]
Q) swap 메소드를 이용하여 변수 num1의 값과 num2의 값을 서로 바꾸는 코드를 만드세요.
1. 아무런 의심없이 배웠던대로 main()를 시작으로 int형 변수 num1과 num2에 값을 초기화하고, swap() 메소드를 호출하여 매겨인자로 변수 num1과 num2를 넘겼을 것이다.
2. 변수 num1을 int형 임시변수 temp에 저장하고 num2는 num1에 저장하고 num2에는 temp에 저장했던 num1을 저장한다.
3. 2개의 출력문을 생성하여 swap() 메소드를 호출하기 전과 후를 비교해보았다.
4. 결론은 똑같다. 왜그럴까?
∴ 프로그램 시작점은 main 메소드로부터 시작하여 num1과 num2는 로컬(지역) 변수니까 main() 스택프레임에 메모리가 할당
된다. swap() 메소드를 호출할 때, num1과 num2를 전달하는데 변수에 저장된 값이 전달이 되고 swap과 관련된
스택프레임이 메모리에 할당된다. swap 스택프레임에 로컬(지역) 변수 temp, num1, num2가 생성되고 temp=5, num1=10,
num2=5로 바뀌는데, 문제는 닫는 브레이스가 끝나면 swap() 메소드 스택프레임에 생성되어있던 변수들은 전부 사라지게된다.
그렇게 때문에 swap() 메소드를 아무리 호출하게되더라도 두 변수 num1과 num2의 값을 바꿀 수 없다.(call by value)
** call by value : 메소드의 파라미터로 호출자(caller)가 제공한 값을 전달하는 방식이다. 파라미터 값이 복사되어
전달되므로, 호출자의 값은 수정되지 않는다. 자바는 call by value 방식을 따른다.
만약 값을 변경하고싶다면 참조형 타입을 이용하여 주소를 전달하게되면 변경이 가능하게된다.(call by Reference)
** call by reference : 메소드의 파라미터로 호출자(caller)가 제공한 값의 위치를 전달하는 방식이다. 파라미터로 값의
참조가 전달되므로, 호출자의 값이 수정될 수 있다.