[JAVA] 제어문

SungBum Park·2021년 3월 7일
0

JAVA

목록 보기
4/9
post-thumbnail

제어문은 프로그램의 흐름을 제어하는 문법을 말한다. 제어문에는 선택문(조건문)과 반복문 두 가지로 나뉜다. 프로그램을 개발한다는 것은 제어문을 통해 프로그램의 흐름을 만드는 것으로 봐도 무방하다. 그만큼 개발을 위해 기본적으로 익혀야하는 문법이다.

선택문

선택문은 어떠한 조건을 만족할 때 선택되도록 만드는 문법이다. 자바는 선택문으로 if-else 문, switch 문을 제공한다.

if-else 문

if-else 문은 매우 다양한 방식으로 활용할 수 있다. 이를 하나하나 살펴보자.

if 문

먼저 if 문을 하나만 사용하는 모습을 살펴보자.

if ( 조건식 ) {
	실행문;
	실행문;
	...
}

if ( 조건식 )
	실행문;

if 문은 위와 같이 조건식이 참인 경우 if 문 내부로 흐름을 제어하는 문법이다. 만약 조건식이 거짓인 경우는 if 문 내부가 아닌 그 다음 실행문으로 이동한다.

if-else 문

if 문과 else 문 두 가지를 사용하는 모습을 살펴보자.

if ( 조건식 ) {
	실행문;
	...
} else {
	실행문;
}

if-else 문은 if 문의 조건식이 참인 경우는 if 문의 내부 실행문이 동작하지만, 거짓인 경우는 else 문의 내부 실행문이 동작한다. 거짓인 경우에 어떠한 제어를 해야 하는 경우는 else 문을 활용할 수 있다.

if-else if 문

if 문의 조건을 여러가지 경우로 나누고 싶은 경우가 있다. 예를 들어, 학점을 계산한다고 했을 때 90점 이상은 A, 80점 이상은 B 그리고 70점 이상은 C와 같은 조건을 만드려면 if 문이나 if-else 문으로는 부족하다.

if ( 조건식 1 ) {
	실행문;
	...
} else if ( 조건식 2 ) {
	실행문;
	...
} else if ( 조건식 3 ) {
	실행문;
	...
} 

위와 같이 조건식이 여러 개인 경우 if 문과 else if 문을 사용하여 제어할 수 있다.

if-else if-else 문

if 문, else if 문, else 문 세 가지를 모두 활용할 수도 있다. 어떠한 조건도 만족하지 않을 때 어떠한 제어를 하고 싶다면 else 문까지 활용할 수 있다.

if ( 조건식 1 ) {
	실행문;
} else if ( 조건식 2 ) {
	실행문;
} else {
	실행문;
}

중첩 if-else 문

조건을 여러 개 중첩으로 만족해야 하는 경우에는 if 문 내부에 또 다른 if-else 문을 사용할 수 있다. 물론 이전에 배운 &&, || 연산자로 하나의 if 문에 여러 조건을 설정할 수 있지만, 하나의 조건을 만족한 후에 다시 조건이 나눠지거나 하는 복잡한 조건을 다뤄야하는 경우가 있다.

if ( 조건식 1 ) {
	if ( 조건식 2 ) {

switch 문

하나의 변수에 있어서 값에 따라 어떠한 행동을 제어해야 한다면 switch 문이 if 문보다 적절할 수 있다.

switch ( 변수 ) {
	case1:
		...
		break;
	case2:
		...
		break;
	default:
		...
}

변수의 값이 값1일 때, 값2일 때 그리고 값1과 값2 모두 아닐 때(default) 어떠한 행동을 제어할 수 있다. switch 문의 특징은 다음과 같다.

  • case 내부에 break 문이 없으면 아래로 내려간다.
  • switch 문 괄호 내부에는 byte, char, int, long과 같은 정수형 타입/정수형 타입을 결과로 하는 연산식/enum/Byte, Short, Integer, Long과 같은 정수형 wrapper 타입/String 이 올 수 있다.
    • 부동소수점은 정밀도가 완전히 정확하지 않아 비교할 수 없어 허용하지 않는다.
  • case의 값은 리터럴 또는 상수가 올 수 있다.
  • 각 case의 값은 고유해야 하며, 중복되는 경우 컴파일 에러가 발생한다.

반복문

반복문은 정해진 구간을 반복하도록 만드는 문법이다. 반복문의 대부분은 반복을 위한 조건을 설정하며, 이 조건이 true인 경우 해당 구간을 반복한다. 따라서 조건에 따라 무한 반복이 발생할 수 있어 이를 주의해야 한다.

자바에서 반복문은 for 문, while 문, do-while 문, for-each 문, stream 으로 나뉜다.

for 문

for 문은 초기 프로그래밍 언어부터 사용해오던 방식으로, 자바에서 역시 사용할 수 있다. 하지만 요즘은 가독성이나 다른 반복문보다 사용이 불편한 점이 있어 사용 빈도가 많이 줄었다.

for ( 초기화식; 조건식; 증감식 ) {
	// 반복할 로직
}

for 문의 문법은 위와 같다.

  • 초기화식: 반복문의 시작으로, 반복문의 조건과 내부에서 사용할 수 있는 변수를 초기화하는 작업을 하는 곳이다. 변수는 초기화식에서 선언하거나, 앞에서 선언된 변수를 초기화할 수 있다.
  • 조건식: 반복을 할지 결정하는 조건을 선언하는 부분이다. 해당 조건식은 boolean 값을 반환해야 하며, ture면 내부 반복문에 접근하고 false면 반복문을 빠져나간다. 만약 아무런 조건식을 선언하지 않으면 무한 반복이 되므로 주의해야 한다.
  • 증감식: 초기화된 변수의 증가 또는 감소를 선언하는 부분이다. 일반적으로는 초기화식에서 초기화한 변수를 증감하지만, 초기화식 이외에도 이미 선언된 변수에 대한 증감을 할 수 있다.

for 문의 동작 과정은 다음과 같다.

초기화식 → 조건식 → 조건식 결과 = true → 내부 반복문 수행 → 증감식 → 조건식 → ...

                   → 조건식 결과 = false → 반복문 빠져나감
  • 초기화식은 for 문이 시작할 때만 수행되며 이후에는 수행되지 않는다.
  • 조건식 결과가 true인 동안은 내부 반복문 수행 → 증감식 → 조건식을 반복한다.

for 문은 변수를 초기화하여 내부 반복문에 사용할 수 있으므로, 인덱스를 가진 배열과 같은 자료구조를 반복하기에 매우 적합한 반복문이다.

while 문

while 문도 for 문과 같이 초기 프로그래밍에서도 흔히 쓰인 반복문이다.

while ( 조건식 ) {
	// 반복할 로직
}

for 문에 비해서 문법이 매우 간단하여, 가독성이 더 좋다.

  • 조건식: 반복을 할지 결정하는 조건을 선언하는 식으로, 해당 조건식이 true면 내부 반복을 수행하고 false면 반복문을 빠져나간다.

무한 반복문을 가장 쉽게 만드는 방법은 while 문을 사용하는 것이다.

while (true) {
	// ...
}

// for 문도 아래와 같이 무한 반복문을 만들 수 있음
for (;;) {
	// ...
}

do-while 문

do-while 문은 앞선 while 문과 유사하지만, 조건식의 위치가 다르다.

do {
	// 반복할 로직
} while ( 조건식 );

문법에서 주의할 점은 마지막에 세미콜론(;)를 반드시 붙여줘야 한다는 점이다.

앞선 while 문은 조건식에 만족해야 내부 반복할 로직을 수행할 수 있지만, do-while 문은 조건식을 검사하기 이전에 먼저 반복할 로직을 수행할 수 있다. 이렇게 로직을 한 번 미리 수행한 후에 조건식에 따라 계속 반복할 지 또는 반복문을 빠져나갈지 결정할 수 있다.

for-each 문

for-each 문은 J2SE 5.0 버전부터 추가된 문법으로, 이전 for 문보다 더욱 직관적으로 사용할 수 있게 되었다.

for ( Iterable 요소 정보 : Iterable ) {
	// 반복할 로직
}

IterableCollection 의 상위 인터페이스로, 우리가 자바에서 아는 대부분의 반복가능한 자료구조(List, Array, Map, Set 등)는 Collection 인터페이스를 구현하는 있다. for-each 문은 Iterable 을 구현하고 있는 자료구조는 위처럼 반복문을 사용할 수 있다. 좀 더 쉽게 예제를 보자.

List<String> names = Arrays.asList("Mike", "Bob", "Alice");
for (String name : names) {
	System.out.println(name);
}

위의 수행 결과는 아래와 같다.

Mike
Bob
Alic

이처럼 for-each 문은 기존 for 문보다 쉽게 사용할 수 있다. 위 방법뿐 아니라 Iterable 인터페이스를 구현한 자료구조는 직접 forEach() 메서드를 호출하여 사용할 수도 있다.

// names 리스트는 위와 동일
names.forEach(name -> System.out.println(name));

위 역시 for-each 문과 같은 결과를 볼 수 있다. forEach() 메서드를 직접 살펴보면 for-each 문을 그대로 사용한 것을 볼 수 있다.

default void forEach(Consumer<? super T> action) {
      Objects.requireNonNull(action);
      for (T t : this) {
          action.accept(t);
      }
}

Stream API

Java 8 버전부터 Stream API의 등장으로, 반복문을 직관적이면서 많은 기능을 사용할 수 있다. 사실 stream(스트림)은 기존 for 문이나 while 문과 같은 방식과는 사뭇 다르지만, 스트림을 활용할 수 있는 경우에서는 매우 강력하게 사용할 수 있다. 기존보다 더 직관적이고, 편하고 심지어 더 효율적일 수도 있다. 여기서는 간단히 반복문을 어떻게 다룰 수 있는지만 보고, 자세한 것은 Java 8 Stream API를 찾아보자.

스트림을 사용하여, 위 names ArrayList를 출력하는 예제는 다음과 같다.

List<String> names = Arrays.asList("Mike", "Bob", "Alice");
names.stream()
	.forEach(name -> System.out.println(name));

하나의 예제를 더 살펴보면, 위 names 에서 4글자 이상인 이름만을 출력하고 싶다면 다음과 같이 구현할 수 있다.

names.stream()
	.filter(n -> n.length() >= 4)
	.forEach(System.out::println);  // 이는 람다식을 더 간단히 표현한 방법이다.

현재 스트림은 자주 사용되고 있어, 학습을 해두는 것이 좋을 듯하다. (추천 도서: 모던 자바 인 액션, 많은 분들이 추천하신 책으로 알고 있다.)

참고자료


profile
https://parker1609.github.io/ 블로그 이전

0개의 댓글