[Java] if문과 switch문, 변수의 유효범위(Variable Scope)

김용준·2022년 9월 8일
0

Java Basic

목록 보기
9/22

지금까지의 코드 실행은 위에서 아래로 한 문장씩 순차적으로 진행되었지만 때로는 조건에 따라 문장을 건너뛰거나 특정 문장을 반복해서 수행해야 할 때가 있다.

이처럼 프로그램의 흐름을 바꾸는 문장들을 제어문이라고 한다. 제어문에는 조건문(if문, switch문)과 반복문(for문, while문)이 있다.


if

if (조건식) {
	실행문1;
	실행문2;
	실행문3;
}
  • 조건식이 true로 판정되면 블록내부의 실행문들이 수행된다.
  • 조건식의 false로 판정되면 실행문들을 수행하지않고 if문 블록을 빠져나온다.
  • 조건식의 연산결과는 반드시 boolean타입이어야 한다.
  • 조건식은 주로 비교 연산자, 논리 연산자를 사용하는 연산식이 사용된다.

괄호{}를 이용해서 여러 문장을 하나의 단위로 묶을 수 있는데, 이것을 '블럭'이라고 한다. 블럭은{로 시작해서 }로 끝나며, }다음 문장의 끝을 의미하는 ;를 붙이지 않는다.

블럭 안에는 보통 여러 문장을 넣지만, 한 문장만 넣거나 아무런 문장을 넣지 않을 수 있다. 만일 블럭 내 문장이 하나뿐일 때는 다음과 같이 괄호를 생략거나 한 줄로 쓸 수 있다. 그러나 새로운 문장이 추가될 경우 괄호로 감싸주지 않으면 첫 번째 문장만 if문의 문장으로 인식하기 때문에 주의해야한다.

if-else

if (조건식) {
	실행문1;
	실행문2;
} else {
	실행문3;
	실행문4;
}
  • 실행문1, 실행문2는 조건식이 true로 판정될 때 수행
  • 실행문3, 실행문4는 조건식이 false로 판정될 때 수행
  • else 블록은 if 블록없이 단독으로 사용할 수 없음.

if-else문의 구조는 if문에 else블럭이 추가되었을 뿐이다. 조건식의 결과가 참이 아닐 때, 즉 거짓일 때 else블럭의 문장을 수행한다.

조건식의 결과에 따라 두 개의 블럭 중 어느 한 블럭의 내용이 수행되고 전체 if문을 벗어난다. 두 블럭의 내용이 모두 수행되거나, 모두 수행되지 않는 경우는 없다.

두 개의 조건식이 모순관계에 있을 때, 다음과 같이 두 개의 if문을 if-else문으로 바꿀 수 있다. 두 명제가 동시에 참이 되거나 거짓일 수 없을 때 '모순관계'에 있다고 한다.

    두 개의 if문
if (input == 0) {
System.out.println("0입니다.");
}
if (input != 0) {
System.out.println("0이 아닙니다.");
}


    if-else문
if (input == 0) {
System.out.println("0입니다.");
} else {
System.out.println("0이 아닙니다.");
}

if-else if

if (조건식) {
	실행문1;
} else if (조건식2) {
	실행문2;
} else if (조건식3) {
	실행문3;
} else {
	실행문4;
}
  • 검사할 조건이 여러 개일 때 사용하는 제어문.
  • 조건식1이 true로 판정되면 실행문1을 실행하고, 나머지 부분은 전부 skip한다.
  • 조건식1이 false로 판정되면 조건식을 만족하는 else if 블럭까지 순서대로 내려간다.
  • 마지막 else 블럭은 제시된 모든 조건식이 false로 판정되었을 때 실행된다.
  • else 블럭은 생략가능하다.
  • 각 블럭의 실행문은 절대로 동시에 시행될 수 없다.
  • 조건식들이 중복 불가능할 때 사용한다.

if-else문은 두 가지 경우 중 하나가 수행된다. 처리해야 할 경우의 수가 셋 이상인 경우에는 if-else if문을 사용한다. if-else if문은 한 문장에 여러 개의 조건식을 쓸 수 있다.

첫 번째 조건식부터 순서대로 평가하여 결과가 참인 조건식을 만나면 해당 블럭만 수행하고 if-else if문 전체를 벗어난다. 만일 결과가 참인 조건식이 하나도 없으면, 마지막의 else블럭의 문장들을 수행한다. else블럭은 생략이 가능하고, 생략되었을 때는 if-else if문의 어떤 블럭도 수행되지 않을 수 있다.

다음은 점수를 입력하면 해당하는 학점을 출력하는 if-else if문의 예제이다.

import java.util.Scanner;

public class Ex4_4 {

	public static void main(String[] args) {
    
		int score = 0; 
		char grade = ' '; 
		
		System.out.print("점수를 입력하세요. >");
		Scanner scanner = new Scanner(System.in);
		score = scanner.nextInt();

		if (score >= 90) {
			grade = 'A';
		} else if (score >= 80) { 
			grade = 'B';
		} else if (score >= 70) {
			grade = 'C';
		} else {
			grade = 'D';
		}
		System.out.println("당신의 학점은 "+ grade + "입니다.");
	}
}

짚고 넘어가야 할 부분이 있다. 두 번째 조건식을 보면 score가 90점 미만이고, 80점 이상인 사람에게 'B'학점을 준다. 그런데 조건식을 score >= 80으로 쓸 수 있는 것은 첫 번째 조건식에서 이미 score >=90은 거짓이라는 것을 확인하고 두 번째 조건식으로 넘어왔기 때문이다. score >= 90이 거짓이라는 것은 score < 90이 참이라는 뜻이므로 두 번째 조건식에서 중복해서 확인할 필요가 없다.

그리고 grade의 초기값을 'D'로 둔다면 마지막 else블럭을 생략할 수 있고 코드를 보다 간결하게 작성할 수 있다. if-else if문에서 결과가 참인 조건식이 없으면 if-else if문의 어떤 블럭도 수행되지 않고, 마지막 문장이 실행되기 때문이다.

중첩 if문

if (조건식1) {
	실행문1;
	if (조건식2) {		// 중첩된 if문
		실행문2;
	}
} else {
	실행문3;
}
  • 중첩된 if문은 조건식이 true로 판정될 때만 조건식2를 검사해서 실행문2의 실행여부를 결정한다.
  • 중첩된 if문은 if 블록 또는 else 블록 내부에 정의된 if문이다.
  • 조건식들이 중복 가능할 때 사용할 수 있다.

중첩 if문은 if문 블럭 내에 또 다른 if문을 포함시키는 것이다. 중첩의 횟수에는 거의 제한이 없다. 위와 같이 내부의 if문은 외부의 if문보다 안쪽으로 들여쓰기를 해서 두 if문의 범위가 명확히 구분될 수 있도록 작성해야한다.

다음은 중첩if문을 사용하는 예제이다.

public class If {
	
	public static void main(String[] args) {
		
		/*
		 * 국어, 영어, 수학점수를 입력받아서 합격여부, 장학금 지급여부를 출력하는 프로그램
		 * 평균점수가 60점 이상이면 합격, 97점 이상이면 장학금 지급대상이다.
		 * 단, 한 과목이라도 40점 미만이면 과목낙제 불합격이다.
		 */
		
		KeyboardReader keyboard = new KeyboardReader();
		
		System.out.print("국어점수: ");
		int korScore = keyboard.getInt();
		System.out.print("영어점수: ");
		int engScore = keyboard.getInt();
		System.out.print("수학점수: ");
		int mathScore = keyboard.getInt();
		
		double average = (korScore + engScore + mathScore)/3.0;
		
		if (korScore < 40 || engScore < 40 || mathScore < 40) {
			System.out.println("과목낙제 불합격입니다.");
		} else if (average >= 60) {
			System.out.println("합격입니다.");
			if (average >= 97) {
				System.out.println("장학금 지급대상입니다.");
			}
		} else {
			System.out.println("평균 60점 미만이므로 불합격입니다.");
		}
	}
}

여사건을 활용한 if

if문을 프로그램의 요구사항에 반하는 조건식으로 작성하여, 그 조건에 해당하는 경우 메소드를 즉시 종료시킨다. 실행문이 수행될 수록 여사건이 소거되고, 프로그램의 요구사항을 만족하는 경우만 남게된다.

앞의 중첩 if문을 여사건을 활용한 if문으로 작성한 예제다.

import utils.KeyboardReader;

public class If5 {

	public static void main(String[] args) {
    
    	KeyboardReader keyboard = new KeyboardReader();
		
		System.out.print("국어점수: ");
		int korScore = keyboard.getInt();
		System.out.print("영어점수: ");
		int engScore = keyboard.getInt();
		System.out.print("수학점수: ");
		int mathScore = keyboard.getInt();
			
		//과목낙제가 있는 경우 메세지를 출력하고 main메소드를 즉시 종료시킨다.
		if (korScore < 40 || engScore < 40 || mathScore < 40) {
			System.out.println("과목낙제로 불합격입니다.");
			return;
		}
		
		double average = (korScore + engScore + mathScore)/3.0;
		
		// 평균 60점 미만인 경우 메세지를 출력하고 main메소드를 즉시 종료시킨다.
		if (average < 60) {
			System.out.println("평균 60점 미만이므로 불합격입니다.");
			return;
		}
		
		// 두 번째 if문을 통해 평균 60점 미만이 거짓임을 확인했다. 합격 메세지를 출력한다.
		System.out.println("합격입니다.");
        
        // 평균 97점인 경우 장학금 지급 메세지를 출력한다.
		if (average >= 97) {
			System.out.println("장학금 지급 대상입니다.");
		} 
	}
}

합격할 수 없는 조건들을 각각의 if문으로 미리 소거했다. if문의 구조가 단순해지고 코드의 가독성이 향상되므로 가능하다면 중첩 if문보다는 이 방법을 쓰는 편이 낫다.


Switch

switch(조건식) {
	case 값1:
		실행문1;
		break
	case 값2:
		실행문2;
		break
	default:
    	실행문3;
}
  • 조건식의 결과가 값1과 일치하면 실행문1이 실행되고, 값2와 일치하면 실행문2가 실행된다.
  • 조건식이 값1과 값2와 전부 일치하지 않으면 default문을 실행한다.
  • 각 실행문이 실행되면 break문을 만나 switch문을 빠져나간다.
  • 각각의 case 마다 실행문의 마지막에 break문이 필요하다.
  • 조건식이 값1과 값2와 전부 일치하지 않으면 default문을 실행한다.
  • 조건식의 결과는 반드시 정수, 문자 혹은 문자열이어야 한다.

switch문의 실행 순서는 다음과 같다.

  1. 조건식을 계산한다.
  2. 조건식의 결과와 일치하는 case문으로 이동한다.
  3. 해당 case문의 실행문을 실행한다.
  4. break문을 만나면 switch문 전체를 빠져나간다.
  5. 조건식의 결과가 모든 case문의 값과 일치하지 않으면 default문으로 이동한다.

switch문은 하나의 조건식으로 많은 경우의 수를 처리할 수 있다. 그러나 제약조건이 있기 때문에 상황에 맞게 if문과 switch문을 선택해야 한다.

switch문에는 제약조건은 조건식의 결과값이 반드시 정수 또는 문자열이어야 한다는 점이다. 따라서 당연히 case문의 값도 정수 또는 문자열이어야 하고 중복되지 않아야 한다.

다음은 switch문의 예제이다.

public class Switch {
	
	public static void main(String[] args) {

		String grade = "골드";
		int orderPrice = 300000;
		
		int point = 0;
		switch (grade) {
		case "골드":
			System.out.println("골드등급 고객의 포인트를 계산 중.");
			point = (int) (orderPrice*0.03);
			break;
		case "실버":
			System.out.println("골드등급 고객의 포인트를 계산 중.");
			point = (int) (orderPrice*0.02);
			break;
		case "브론즈":
			System.out.println("골드등급 고객의 포인트를 계산 중.");
			point = (int) (orderPrice*0.01);
			break;
		default:
			System.out.println("등급이 없는 고객의 포인트를 계산 중.");
			point = (int)(orderPrice*0.005);
		}
		System.out.println("====================");
		System.out.println("고객등급: " + grade);
		System.out.println("구매금액: " + orderPrice);
		System.out.println("적립포인트: " + point);
		System.out.println("====================");
	}
}

변수의 범위

Java에서 변수의 유효범위는 그 변수가 생성된 블록이다. 닫는 괄호를 만나면 해당 블록에서 생성된 변수는 즉시 사라진다. 그리고 변수의 영향은 생성된 이후부터 영향을 미친다. 따라서 어느 시점에 변수를 선언해야할지 고려하는 것이 중요하다.

변수의 유효범위를 '변수의 스코프(Variable Scope)'라고 한다. 변수의 유형에 따라 Variable Scope가 다르고 할당되는 메모리 영역이 다른데, 보다 구체적인 내용은 다음에 다루기로 한다. 우선 변수가 선언된 블록을 벗어나면 해당 변수는 사라진다는 것만 알아두기로 하자.

다음의 예제를 보자

public class VariableScope {

	public static void main(String[] args) {
		
		boolean result = false;
		
		if (result) {
			int n = 1;
			System.out.println(n);
		}		
		n = 3;	// 에러, n이 if블럭에서 선언되었기 때문에 else블럭에서는 사용할 수 없다. 
		System.out.println(n);
		}
	}
}

앞서 설명한 것과 같이 if문 내부에서 변수n이 선언되었기 때문에 해당 if문 블럭이 닫히면 변수n은 사라진다. 그래서 if문이 종료된 후에도 n을 사용하고 싶다면 아래 예제와 같이 if문 밖에서 n을 선언해야 한다.

public class VariableScope {

	public static void main(String[] args) {
		
		boolean result = false;
		int n;
		
		if (result) {
			n = 1;
			System.out.println(n);
		}	
		n = 3;				
		System.out.println(n);
		}
}
profile
차선이 모여 최선이 된다.

0개의 댓글