자바 제어문과 반복문

Tina Jeong·2021년 1월 15일
0

Re-자바

목록 보기
7/16

제어문

if문

if문은 가장 기본적인 제어문이다. if(조건식)의 형태로, 조건식은 true나 false로 판별되어야 한다. 선택적으로 else if()else를 덧붙이는 방식으로 조건을 분기하여 처리할 수 있다.

if(name.equals("Tina") {
...
}
else if(name.equals("Jeong")) {
...
}
else {
...
}

wrapper class인 Boolean이 조건식에 들어간 경우엔 원시 타입으로 auto unboxing된다. bool.booleanValue() 메소드를 통해 unboxing할 필요가 없다.

Boolean bool = Boolean.TRUE;
if(bool.booleanValue()) System.out.println(true);
if(bool) System.out.println(true);

else문의 결합 우선 순위

if문의 문법 자체는 어렵지 않지만, nested if문인데다가 중괄호로 묶지 않았을 경우 프로그래머의 의도와 다르게 else문이 엉뚱한 if문과 묶여서 처리될 수도 있다.

아래 프로그램의 의도는 정씨인 사람 중에 이름이 티나인 사람을 출력하고, 정씨가 아니라면 그 사람의 uuid를 출력하는 것이다.

if(lastName.equals("Jeong")) System.out.println(lastName);
      if(firstName.equals("Tina")) System.out.println(firstName);
else System.out.println(uuid);

만약 Tina Kim이 입력이었다면 Tina와 uuid가 출력되어야 한다. 그러나, 프로그램을 실행해보면 Tina만 출력된다. 왜냐하면 중괄호로 분기를 명확하게 묶어주지 않은 else문은 가장 가까운 if문에 결합되기 때문이다.

의도에 맞게 프로그램을 실행시키려면 중괄호를 통해 명확하게 분기를 구별해주는 것이 좋다.

if (lastName.equals("Jeong")) {
      System.out.println(lastName);
      if (firstName.equals("Tina")) System.out.println(firstName);
} else {
      System.out.println(uuid);
}

switch

ifelse if문을 사용해 변수값의 경우의 수를 나누어 처리할 수 있다.

int a;
...
if(a==-1) {...
}
else if(a==0) {...
}
else if(a==1) {...
}
else if(a==2) {...
}
else {
...
}

switch문은 하나의 변수값에 대해 위와 같이 if문 아래로 else if문들이 늘어진 경우 verbose함을 줄이고, 가독성을 높여줄 수 있는 제어문이다.

switch(a) {
	case -1:
    		...
        	break;
   	case 0:
    		...
        	break; 
	case 1:
    		...
        	break;
	case 2:
    		...
        	break;
    	default :
    		...
}

default case는 optional이라 else 케이스가 없는 경우에는 사용할 필요가 없다.

break;를 사용하자

각 케이스마다 break;문을 넣어준 이유는, break가 없으면 값이 매칭된 case부터 switch문이 끝날때까지 모든 라인을 실행하기 때문이다. 만약 a의 값이 0라면 case 0부터 default 부분까지 모두 실행하게 된다. 물론 모든 라인을 실행하는 것이 프로그래머의 의도일 수 있지만, 일반적인 활용은 경우에 따른 분리된 처리이기 때문에 break;를 꼭 써주어야 한다.

윤달 판별 시 switch문 활용하기

윤달 판별 프로그램은 case 별로break;을 사용하지 않는 예외적인 케이스라 참고용으로 가져왔다. if,else if 를 사용하는 것보다 훨씬 간결해서 대부분 switch문을 활용해 구현한다.

switch (month) {
      case 1:
      case 3:
      case 5:
      case 7:
      case 8:
      case 10:
      case 12:
          numDays = 31;
          break;
      case 4:
      case 6:
      case 9:
      case 11:
          numDays = 30;
          break;
      case 2:
          if (((year % 4 == 0) &&
                        !(year % 100 == 0))
                        || (year % 400 == 0))
          	numDays = 29;
          else
	   	numDays = 28;
           	break;
      default:
          System.out.println("Invalid month.");
          break;
        }
System.out.println("Number of Days = "+ numDays);

참조타입도 switch문 사용가능

자바의 switch문에서 사용 가능한 원시 타입은 int, short, char, byte이고, 각각의 wrapper class(Integer, Short, Character, Byte)도 가능하다. String과 enum도 가능하다.

반복문

for

가장 많이 사용하는 반복문인 for문 부터 정리한다.

for (initialize; test; update) {
	statement
}

for문은 제어변수 초기화하는 부분intialize, 제어변수의 조건에 따라 반복 여부를 결정하는 test부분, 제어변수값을 update하는 부분으로 나누어져있다. 제어변수를 for문 안에서 활용하고 싶을 때, 특히 배열 등의 데이터구조에서 인덱스를 통한 원소 접근이 필요할 때 자주 사용한다.

int[] nums = new int[10];

for(int i=0 ; i<nums.length;i++) {
	nums[i] ...
}

enhanced for

Java 8 버전부터는 제어변수가 없는 enhanced for문을 제공한다. 제어변수가 필요는 없지만, Collection이나 배열을 순회할 때 자주 사용한다. 결과적으로 인덱스를 통한 원소 접근은 불가하다.

for (로컬변수선언 : 참조변수이름)

로컬변수를 선언하는 부분에는 초기화를 하지 않는다는 것이 original for문과의 차이이다.

int[] nums = new int[10];

for(int num : nums) {
	sout(num);
}

while

위에 정리한 for문을 while문으로 번역하면 다음과 같다.

initialize;
while (test) {
	statement;
	update;
}

while문은 true/false로 판별되는 test부분의 결과에 따라 반복 여부가 결정된다. for문보다 자유도가 높은 반복문이라고 볼 수 있는데, test부분에서 반복 여부를 결정해도 되고, while(true)로 적어두고 while문 안에서 조건을 판별해 반복 여부를 결정할 수 있다.

while(true) {
	sout(...)
	if(...) break;
}

do while

do-while문은 반드시 한번은 실행하는 while문이다. 즉, 인터프리터가 한줄씩 실행하며 내려오는 원리를 이용해 test 조건을 아래에 두어 do의 부분이 반드시 한번은 실행되도록 했다. original while과 동일한 test 조건을 do while문에 적어둔다면, do while문은 while문의 실행횟수 만큼 돌고, 한번더 반복한다는 사실을 기억한다.

do
	statement
while (expression);

break, continue

break는 반복문에서 쓰일땐 해당 반복문의 실행을 중지하고 빠져나간다. switch문에서 쓰일 땐 해당 케이스만 실행하고 switch문을 빠져나간다. continue문은 반복문에서 실행도중 특정한 조건을 만족할 때는 해당 라인 이후를 실행하지 않고 다음 케이스로 넘어가고 싶을 때 사용한다.

아래의 예시를 보면 원소의 값이 0 미만인 경우 아래 라인들을 실행하지 않고 다음 원소로 넘어간다.

int[] nums = new int[10];

for(int i=0 ; i<nums.length;i++) {
	if(nums[i]<0) continue;
    ...
}

break는 루프 중지하고 빠져나감, continue는 케이스 하나만 skip

Labeled Statements

labeled statements는 숨겨진 꿀팁이라고 할 수 있는데, 반복문에 레이블을 부여해 break
continue를 해당 레이블 반복문에 사용할 수 있다. 원래는 해당 break
continue가 속한 반복문에서만 적용되기 때문이다. 아래 예시는 바깥 루프에 rowLoop를 이용해 colLoop 안에서 rowLoop를 break 시켰다.

rowLoop: for(int r = 0; r < rows.length; r++) { 
	colLoop: for(int c = 0; c < columns.length; c++) { 
		break rowLoop; 
}
}

참고
Java in a Nutsell, 7th Edition
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/while.html

계속해서 문서를 업데이트하고 있습니다. 언제든지 댓글피드백 남겨주세요. 😉

profile
Keep exploring, 계속 탐색하세요.

0개의 댓글