중첩 반복문은 능숙해지기 전까지는 그 난이도가 매우 높기에 진도를 천천히 나가고 있다.
do-while문
do-while문의 기본 구조는 다음과 같다.
do {
수행할 문장;
}
while (조건식);
수행할 문장을 우선 수행한 후 조건식이 참이면 다시 수행할 문장으로 돌아간다.
위의 그림은 순서도로 표현한 각 반복문간의 차이이다.
순서도에서는 문장을 직사각형으로, 분기를 마름모로 표기한다. 그림으로 놓고 보면 조금 더 이해가 쉬워진다.
위의 예제를 보면 우선적으로 do 안의 문장을 먼저 수행하고 while 뒤에있는 조건식으로 간다.
코드를 순차적으로 해석해보되, 주석의 메모와 생각이같은지 점검해봐야한다.
break문
자신이 포함된 가장 가까운 반복문을 벗어난다.
대체하기에는 가독성이 떨어지기 때문에 자주 사용된다.
continue문
break와 반대의 의미로 생각하면 안된다.
continue에 닿는 즉시 자신이 포함된 반복문 문장에서 자신 이하의 문장을 무시하고 종료한다.
하지만 조건을 반대로 바꿔버리거나 여러 방법을 통해 대체가 가능하므로 사용빈도가 낮다.
위의 예제에서 if문의 조건을 만족하면 continue가 되어 i를 출력하라는 문장을 무시해버린다.
이는 if의 조건문을 i%3 != 0 으로 하고 if문 안에 수행할 문장으로 i를 출력하라는 문장을 넣어주면 오히려 가독성이 더 좋아지므로 굳이 continue를 사용할 필요는 없다.
이름붙은 반복문(label)
label이라 불리는 제목을 붙인것이다. 하지만 label은 반복문에만 붙는 것이 아니라 여러곳에 붙을 수 있다.
label과 continue, break를 연결지어 예측해보면 각각 어떤역할을 하는지 정확하게 이해할 수 있을 것이다.
continue와 마찬가지로 label은 코드의 가독성 때문에 사용 빈도가 낮은편이니 이런 방법도 있다 하고 넘어가는 정도로 알아두자.
배열
배열이란 같은 타입의 여러 변수를 하나의 묶음으로 다루는 것을 말한다.
배열또한 변수를 선언할 때와 같이 타입을 같이 명시하여 선언해 주어야 한다.
하지만 배열은 변수와는 달리 각 저장공간이 연속적으로 배치되어 있다는 특징이 있다.
예를들어, int[] = score; 라 하면 int타입의 결과값이 들어갈 수 있는 배열을 score라는 이름의 참조변수로 선언한 것이다.
하지만 아직 이 상태는 배열이 생성된 상태는 아니다.
score = new int[5]; 여기에서 new가 새로운 객체를 생성하므로 여기까지 써 있어야 배열이 비로소 생성된다.
이 의미는 int타입의 5칸짜리 배열을 생성하여 그 주소를 score라는 저장공간에 할당하는 것이다.
즉 score 자체에는 값이 없고 생성된 배열의 주소만 들어가는 것이다.
위에서 참조변수를 선언하고 배열을 생성해 그 주소를 할당하는 것을 나누어 설명했는데 보통은 코드의 가독성 떄문에 이를 한줄에 표현한다. int[] score = new int[5];
이는 변수를 선언함과 동시에 초기화 하는 것과 같은 맥락으로 이해할 수 있다.
후에 배울 내용 이지만 위의 그림을 통해 설명을 들은것이 이해가 잘 간다.
위의 그림은 JVM의 메모리 구조를 간략히 그린 것이다.
우선 프로그램 실행중 생성되는 모든 값들은 heap이라는 공간에 생성된다.
즉 위의 설명에서 생성한 5칸짜리 int타입 배열은 heap이라는 영역에 생기는 것이다.
그리고 그 전에 선언한 int[]타입 참조변수 score는 call stack 영역 안의 main 메서드 영역 안에 존재한다.
배열의 주소값은 16진수로 표현이되는데 배열 안에 들어 있는 값이 아닌 이 주소값이 score에 저장되는 것이다.
그렇기 때문에 score 자체를 출력하면 그 안에 들어있는 16진수로 표현된 배열의 주소값만 출력된다.
이렇게 생성한 후 아무 값도 넣지 않는다면 boolean의 경우 false, 나머지는 0을 기본값으로 하여 기본값이 들어가있다.
배열의 대괄호 안을 index, 순번이라 한다. 모든 배열은 첫번째 칸을 0으로 하며 주소가 저장된 참조변수와 대괄호안의 index를 이용해 실제 배열의 n번째 칸에 있는 값을 출력해낼 수 있다.
위의 Prev2는 반드시 잘 해석해봐야 한다.
배열안에 규칙이 있는 값들을 넣는것으로 예를 들어서 보면, 반복문과 배열이 얼마나 궁합이 잘 맞는지 단번에 알아차릴 수 있다.
문제는 그 다음이다. int[] score2 = score;는 새로운 score2라는 int[]타입 참조변수를 선언하여 score에 있는 주소값을 할당한 것이다.
즉, score나 score2 둘다 배열 안의 값이 아닌 그 주소값이 저장된 것이다.
그렇기 때문에 그 이후에 score2[3] = 100; => score2에 저장된 주소에 있는 배열의 4번째칸에 100이라는 값을 넣는다.
를 했을때, score나 score2 에 저장된 주소의 배열안의 값이 변화하는 것이지 score나 score2 안의 값의 변화는 없다.
그러므로 100이라는 값을 대입한 후 score와 score2로 각 배열의 값을 확인해 보면 (어차피 같은 주소에 있는 같은 배열이기에) 값은 같다.
반드시 일반 변수와 구분지어 생각해야한다.
개념이 어느정도 정리가 됐으면 다시 int[] score = new int[5];를 말로 풀어 써봐야 한다.
=> call stack에 있는 main의 공간에 int[]타입의 참조변수 score를 선언한 후 이 저장공간에 int타입의 값이 들어가는 5칸짜리(20byte) 배열을 생성 후 배열의 주소값을 할당한다.
오늘은 여기까지!!
개념자체가 바로 이해될 만큼 쉬운 내용이 아니기에 내일 마저 이어서 한다.
난이도가 높기 때문에 예제에 대한 해석도 깊게 하고 설명자체도 여러번 하기 위해 시간을 더 많이 할당한다..
머리가 벌써 터질것 같다.