-자바를 다시 복습하기로 했다. 그런데 왜인지 새로 배우는 언어같은 느낌이 있다. 왜냐? 그전에 배운 내용들은 너무 두루뭉술하게 배운 느낌이었다. 이제서야 진짜 디테일하게 자바를 배우는 느낌이 든다. 그전에는 무작정 책에 있는 코드를 따라 작성해보고 뜯어보고가 다였는데, 이제는 문법부터 배우고, 디테일한 것들을 짚어주신 후에 비로소 활용해보고 문제를 풀어보고 하게 되었다. 그래서 그런지 훨씬 더 머리에 쏙쏙 들어왔다. 특히 굉장히 익숙해지지 않았던 배열에 대해 공부했고, 배열에 대해 훨씬 잘 알게 된 느낌이다. 전에는 굳이 배열로 선언해서 사용하고 싶지 않았다. 친숙하지도 않을 뿐더러 잘 모르겠으니까... 그런데 오늘 배우고 나서는 정말 신기하게도 사용을 자주 해야겠다는 생각까지 들었다.
-for(;;)를 이렇게 한다면, 그냥 무한반복이다. 또한, for 안의 조건식은 하나여야하지만(||나 &&으로 엮여서 두개인 경우 말고), 초기값을 주는 부분과 증감식은 여러 식이 와도 상관없다. ,로 구분해주면 몇개든 쓸 수 있다.
-반복문 중 while, do while의 차이를 배웠다. 두가지 전부 다 사용해봤지만, 차이가 있는 것은 몰랐다. while과 do while의 차이는 거의 없다고도 볼 수 있지만, 만약 while의 조건이 false면 while문은 아예 반복문을 실행하지 않는다. 그러나 do while은 어쨌든 do{}를 실행하고 조건식을 확인하고 부합하지 않으면 반복을 더이상 진행하지 않는다. 이 부분만 보면 큰 차이다. 반복의 내용을 아예 실행하지 않는다와 한번은 진행하고 반복을 빠져나간다는 엄청난 차이가 있는 것이니까. 이런 디테일함을 그전에는 전혀 알지 못했다.
-continue와 break. break와 continue는 그전에도 익숙하게 사용해봤다. 그런데 한가지 디테일이 있었다. break가 되는 부분이 넓은 영역이라면 break부터 사용해주는 것이 좋다. 그리고 continue 범위도 역시 마찬가지다. 그렇게 반복문을 빠져나가거나 반복문에서 실행하기 싫은 범위를 먼저 설정해주면 아래의 내용을 더 편하게 작성할 수 있다. 되게 사소한 팁인데, 문제를 풀 때 이렇게 하면 훨씬 더 편했다.
-오후는 거의 멘붕이었다. 사실, 나는 비교적 이해를 한 편인데...역시 이해가 안되는 부분을 혼자서 찾아보고 이해안되는 부분을 읽고 또 읽어본 노력이 빛을 발했다.
그래도 대면 수업을 하는 오늘의 반 분위기는 처참했다. 한숨소리까지 들렸었다. 사실 배열이 조금 어렵긴 했지만, 배열을 선언하고 크기를 할당했을 때, 배열명에는 레퍼런스 값, 즉 주소값이 들어간다고 알려주셨다. 나는 이 부분을 찾아봐서 알고는 있었지만 훨씬 더 편하게 설명해주셨다. 책에는 일반 변수의 경우 stack 영역에 해당 변수의 값이 바로 입력되는데, 배열의 경우 stack영역에 레퍼런스 값이 입력되고 그 레퍼런스가 가리키는 heap영역에 실제 값들이 입력된다고 되어있었다. 오늘 교수님이 설명해주신 것은 훨씬 더 간략했다.
배열의 배열명은 그 배열의 시작 주소를 가리킨다.
특히 아파트로 예시를 들어주셨었는데, 그 내용이 정말 이해하는데 큰 도움이 되었다.
사실, 여기까지는 거의 대부분 이해를 했었는데, 그 뒤의 내용이 다른 사람들은 이해가 조금 힘들었나보다.
교수님은 메소드의 인자로 변수를 넘겼을 때와 배열명을 넘겼을 때의 상황을 설명하시면서, 인자로 넘어간 것은 값이 넘어간 것이고, 그렇다면 변수와 배열명이 넘어갔을 때의 차이를 설명해주셨다. 변수가 넘어간 경우 그 변수의 값을 받는 새로운 변수가 선언되고 해당 영역이 생기는 것이고 그 메모리 영역에 그 변수의 값이 넣어지는 것이다. 그리고 해당 메소드에서 값을 변경한다고 해도 처음 넘긴 변수 안의 값은 변하지 않는다. 물론, return시켜서 직접 해당 값을 넣어주면 바뀌겠지만...
그런데, 배열명을 넘기는 경우는 다르다. 배열명을 넘기면 그 배열명이 가진 배열의 시작 주소값이 넘어간다. 그러면 그 시작주소값을 받는 또다른 배열명이 선언되고, 해당 배열은 동일한 주소값을 가진다. 그러면 두 주소가 가리키는 곳은 같을까? 다를까?
같다! 결국 주소값이 다른 두 곳에 적혀있는것이고, 동일한 곳을 가리킨다. 즉, 메소드에서 내용을 바꾼다면, 원래 배열이 가리키는 곳의 내용이 바뀐 것이기 때문에 둘 다 내용이 변하는 것이다.
메소드에 인자를 넘기는 것은 값을 넘긴다! 이 부분이 핵심이다.
또한, 배열명을 넘기는 것과 변수를 넘기는 것의 차이가 있다! 이 부분도 핵심이었다.
아 정말 좋은 수업이었다.
수업때는 그냥 그림과 말로만 설명해주셨었는데, 그 설명도 정말 좋았지만, 수업이 끝나고 나는 코드로 그 부분을 증명해보고 싶었다.
그래서 직접 코드를 작성해봤다.
public class Prac1019_2 {
/**
* @param args
*/
public static void main(String[] args) {
MethodGather mg = new MethodGather();
int a = 5;
System.out.printf("int a의 값은 %d입니다.\n", a);
mg.methodP(a); //methodP에 a 값을 넘김
System.out.printf("int a의 값을 다시 출력합니다. int a의 값은 %d입니다.\n", a);
//메소드를 출력하고 나서, a의 값은 변하지 않음. 즉, a를 넘긴 것이 아니라, a가 가진 값을 넘긴 것!
/*
* 결과:
* int a의 값은 5입니다.
* int x의 값은 6입니다.
* int a의 값을 다시 출력합니다. int a의 값은 5입니다.
*
* */
//메모리 영역에 a의 영역이 생기고 그곳엔 5라는 값이 들어있고, 그 값인 5를 x로 넘긴 것,
//메모리 영역에 x의 영역이 새로 생기고, 해당 메소드가 종료되면
//x의 영역은 사라짐. x는 methodP메소드 안에서 선언된 지역변수이기 때문
//즉, a의 값은 변하지 않음, x의 값도 사라짐.
System.out.println("====메소드로 배열명을 보내는 경우===============");
int[] arrayOne = new int[3];
int i;
//배열은 객체이기 때문에, 선언과 동시에 컴파일러가 자동으로 초기화해줌. 초기값은 int이기 때문에 전부 0이 들어가 있음.
//그래도 가시성을 높이기 위해 배열에 값을 넣어주자. 각각, 5, 10, 15를 넣어줌.
arrayOne[0] = 5;
arrayOne[1] = 10;
arrayOne[2] = 15;
//우선 메소드로 보내기 전 arrayOne 배열을 출력
System.out.println("methodP(int[] y)로 arrayOne을 보내기 전 출력합니다.");
for(i=0;i<arrayOne.length;i++) {
System.out.printf("arrayOne[%d] = %d\n", i, arrayOne[i]);
}
System.out.println();
System.out.println("arrayOne의 값을 받은 y배열을 출력합니다.");
mg.methodP(arrayOne); //오버로딩한 methodP에 arrayOne의 값을 넘김
//메소드를 보면 알겠지만, 각 인덱스가 가진 값마다 +1을 해주었음.
System.out.println();
for(i=0;i<arrayOne.length;i++) {
System.out.printf("arrayOne[%d] = %d\n", i, arrayOne[i]);
}
/*
* 결과:
* arrayOne[0] = 5
* arrayOne[1] = 10
* arrayOne[2] = 15
* y[0] = 6
* y[1] = 11
* y[2] = 16
* arrayOne[0] = 6
* arrayOne[1] = 11
* arrayOne[2] = 16
*/
//결과를 보면 알 수 있듯, methodP(arrayOne)으로 넘긴 값은, arrayOne이 가진 주소값이고, y도 역시 주소값을 가지고 있다.
//이 때, y[0],y[1],y[2]의 값을 변경하면, 해당 주소를 찾아가서 그 안에 있는 값이 변경되는 것이기 때문에
//arrayOne[0],arrayOne[1],arrayOne[2]의 값 역시 변경된다. 즉, arrayOne과 y가 가진 주소값은 동일한 집을 보고 있는 것.
//y[0], y[1], y[2]의 값을 변경한다는 것은 그 주소가 가진 집 안의 내용을 바꾸는 것이고, 그와 주소를 가진 arrayOne의
//arrayOne[0], arrayOne[1], arrayOne[2]의 값도 동일하게 바뀐 값이 나오는 것.
}
}
class MethodGather{
//메소드 오버로딩으로 동일한 이름에 파라미터 변수 타입만 다른 메소드 methodP를 정의함
void methodP(int x){
x= x+1;
System.out.printf("int x의 값은 %d입니다.\n", x);
}
void methodP(int[] y) {
y[0] = y[0]+1;
y[1] = y[1]+1;
y[2] = y[2]+1;
for(int i=0; i<y.length;i++) {
System.out.printf("y[%d] = %d\n", i, y[i]);
}
}
}
오늘 오후 수업 내용의 핵심은 바로 여기에 다 적혀있다. 스스로 생각해서 직접 작성했고 정리하면서 더 제대로 배운 느낌이었다. 글로 공책에도 이클립스에도 작성했지만, 그렇게 글로 하는 것보다 이렇게 코드로 작성하니까 훨씬 뚜렷해졌다. 오늘의 정리는 이것만 해도 굉장히 뿌듯했다. 물론, 오늘 내주신 문제를 다 다시 풀어봤었지만 그 모든 문제들보다 더 뿌듯한 것 같다.
-내일은 오전에 배열을 다시 복습하는 느낌으로 또 배우고, 오후에는 교수님이 병원으로 인해 잠시 자리를 비우기 때문에, 문제를 내주고 가신다고 하셨다. 문제를 푸는 과정에서 서로 의논해도 된다고 했는데, 나는 비대면이라서 그냥 학원을 가야하나 고민중이다. 교수님은 나오길바라셨는데, 내 컨디션이 될지 모르겠다. 일단 최대한 나가는 방향으로 생각하고 있다. 일단 오늘은 이만, 운동하고 영어공부하고 자야겠다. 내일도 파이팅!