1. 식 vs 문
Java의 모든 구문은 두 가지 범주로 나뉩니다: 문 (Statement)과 식 (Expression). 문은 보통 “실행된다”고 말하고, 식은 “계산된다”고 말하죠. 하지만 이것이 핵심은 아닙니다.
문과 식의 가장 큰 차이는 식에는 계산 결과가 있다는 점입니다. 그 결과에는 첫째, 타입이 있고, 둘째, 그 결과를 어딘가에 대입하거나 다른 식에서 사용할 수 있습니다.
예시:
| 코드 | 설명 |
|---|---|
|
문 |
|
식, 타입은 boolean |
|
식, 타입은 변수 i의 타입과 동일 |
|
식, 타입은 변수 x의 타입과 동일 |
그럼 이게 우리에게 어떤 이점을 줄까요?
첫째, 실제로 많은 문이 식(계산 결과를 가짐)이기도 하다는 점을 활용할 수 있습니다. 예를 들어, 이런 코드는 정상 동작합니다:
int x, y, z;
x = y = z = 1; // x = (y = (z = 1));
둘째, 원한다면 식의 계산 결과를 무시할 수도 있습니다.
console.nextLine(); // 입력 결과는 무시함
예를 들어, 어떤 식이 결과를 돌려주는 것 외에도 유용한 부수 효과를 낸다면, 우리는 그 동작만 중요하고 결과 자체는 중요하지 않을 수 있으므로 결과를 무시해도 됩니다.
2. 삼항 연산자
이번 팁은 이전 것보다 더 흥미롭습니다. Java에는 특별한 삼항(세 항) 연산자가 있습니다. 이는 if–else의 축약형과 비슷합니다:
Condition ? Expression1 : Expression2;
조건이 참이면 식1이 평가되고, 그렇지 않으면 식2가 평가됩니다. 조건 뒤에는 물음표가 오고, 두 식은 콜론으로 구분됩니다.
삼항 연산자가 if-else와 다른 가장 큰 점은, 삼항 연산자는 식이므로 그 결과를 어떤 것에든 대입할 수 있다는 것입니다.
예를 들어, 두 수의 최솟값을 구하고 싶다고 해봅시다. 삼항 연산자를 사용하면 코드는 이렇게 됩니다:
int a = 2;
int b = 3;
int min = a < b ? a : b;
또는 어떤 조건에 따라 변수에 서로 다른 값을 대입해야 한다면 어떻게 할까요?
첫 번째 방법 — if-else를 사용합니다:
int age = 25;
int money;
if (age > 30)
money = 100;
else
money = 50;
두 번째 방법 — 삼항 연산자, 즉 if-else의 축약형을 사용합니다:
int age = 25;
int money = age > 30 ? 100 : 50;
그렇다면 무엇을 쓰는 게 좋을까요: if-else일까요, 삼항 연산자일까요? 실행 속도 관점에서는 큰 차이가 없습니다. 여기서는 코드의 가독성이 더 중요합니다. 그리고 이것은 아주 중요한 포인트입니다: 코드는 올바르게 동작해야 할 뿐 아니라 다른 개발자들이 쉽게 읽을 수 있어야 합니다.
가장 단순한 기준은 이렇습니다: 코드가 한 줄에 들어간다면 삼항 연산자를, 한 줄을 벗어나기 시작하면 if-else를 사용하세요.
3. 동작상의 유의점
값의 타입
중요한 점: 삼항 연산자의 두 분기(<참일 때의 값>과 <거짓일 때의 값>)는 같은 타입이거나 호환 가능해야 합니다(예: 둘 다 String 또는 둘 다 int).
작동 예:
int a = 10, b = 20;
int max = (a > b) ? a : b; // 두 분기 모두 int
컴파일 오류:
int a = 10, b = 20;
// String과 int는 호환되지 않음
String result = (a > b) ? "더 큼" : 0; // 컴파일 오류: int 값을 String 타입 변수에 대입할 수 없음
올바른 방법:
int a = 10, b = 20;
String result = (a > b) ? "더 큼" : "작거나 같음";
예: 숫자 처리
삼항 연산자로 절댓값을 계산해 봅시다:
int number = -5;
int abs = (number >= 0) ? number : -number;
System.out.println(abs); // 5
4. 애플리케이션에 삼항 연산자 적용
간단한 대화형 애플리케이션을 작성해 봅시다: 인사말 외에도, 프로그램은 사용자에게 내년의 나이를 알려주고 성인 여부를 표시합니다.
System.out.print("이름을 입력하세요: ");
String name = console.nextLine();
System.out.print("나이를 입력하세요: ");
int age = console.nextInt();
int nextYear = age + 1;
String status = (nextYear >= 18) ? "성인" : "미성년자";
System.out.println("안녕하세요, " + name + "! 내년에 당신의 나이는 " + nextYear + "살이 됩니다. 당신은 " + status + "입니다.");
세부 설명:
변수 status는 삼항 연산자로 계산됩니다: 내년 나이가 18세 이상이면 사용자는 성인(혹은 그대로 성인)입니다.
5. 중첩된 삼항 연산자 — 주의!
삼항 연산자는 서로 중첩할 수 있습니다(각 분기 안에 또 다른 삼항 연산자가 올 수 있음). 하지만… 보통 이런 코드는 읽는 사람의 머리를 아프게 합니다(심지어 2일 뒤의 당신 자신이라도요).
예: 나이에 따른 카테고리 결정
String category = (age < 7) ? "미취학 아동" :
(age < 18) ? "학생" :
(age < 65) ? "성인" : "은퇴자";
의사 결정 표:
| 나이 | 조건 | 결과 |
|---|---|---|
| < 7 | |
미취학 아동 |
| 7–17 | |
학생 |
| 18–64 | |
성인 |
| 65 이상 | 그 외 | 은퇴자 |
이 정도 코드는 그나마 읽을 만하지만, 로직이 더 복잡하다면 if-else if-else를 사용하는 것이 좋습니다.
6. 꿀팁: 삼항 연산자와 타입 boolean
가끔 다음과 같은 코드를 쓰기도 합니다:
boolean adult = (age >= 18) ? true : false;
하지만 이는 중복입니다. (age >= 18) 자체가 이미 boolean을 반환합니다. 따라서 다음처럼 줄일 수 있습니다:
boolean adult = (age >= 18);
GO TO FULL VERSION