업캐스팅은 더 큰 용량의 자료형으로 변환하는 것(예: char → int)이다.
다운캐스팅은 더 작은 용량의 자료형으로 변환하는 것(예: int → char)이다.
업캐스팅은 비교적 안전해서 암시적 변환이 가능한 경우가 있지만,
다운캐스팅은 데이터 손실/오버플로우 위험이 있어서 명시적 변환만 가능하다.
// 업캐스팅 #1 (명시적)
char cast1 = 'A';
System.out.println("원형: " + cast1);
System.out.println("변형(int): " + (int)cast1); // 65
// 업캐스팅 #2 (암시적)
char cast3 = 'b';
int casted3 = cast3; // (int) 없이도 가능
System.out.println("원형: " + cast3);
System.out.println("변형(int): " + casted3);
// 다운캐스팅 #1 (명시적)
int cast4 = 99;
System.out.println("원형(int): " + cast4);
System.out.println("변형(char): " + (char)cast4);
// 다운캐스팅 #2 (명시적)
int cast5 = 100;
char casted5 = (char) cast5;
System.out.println("원형(int): " + cast5);
System.out.println("변형(char): " + casted5);
if는 조건식이 true일 때만 실행된다.
if-else는 true면 if 블록, false면 else 블록이 실행된다.
else-if는 조건을 여러 개 순서대로 검사하며, 위에서 걸리면 아래는 실행되지 않는다.
int num1 = 10;
if(num1 > 0) {
System.out.println("num1은 양수입니다.");
}
if(num1 < 15) {
System.out.println("num1은 15 미만입니다.");
}
int num2 = 0;
if(num2 > 0) {
System.out.println("num2는 양수입니다.");
} else {
System.out.println("num2는 음수입니다.");
}
final 키워드가 붙은 변수는 재대입이 불가능한 상수로 사용한다.
등급 기준 포인트처럼 “변하지 않는 기준값”을 만들 때 유용했다.
상수는 보통 대문자 + 스네이크케이스(SNAKE_CASE)로 작성한다.
final int VIP_POINT = 100;
final int GOLD_POINT = 80;
final int SILVER_POINT = 60;
final int BRONZE_POINT = 40;
입력 포인트에 따라 VIP/GOLD/SILVER/BRONZE/GENERAL로 분기 처리했다.
조건을 위에서부터 순서대로 검사하는 게 핵심이다.
Scanner scanner = new Scanner(System.in);
final int VIP_POINT = 100;
final int GOLD_POINT = 80;
final int SILVER_POINT = 60;
final int BRONZE_POINT = 40;
System.out.print("포인트를 입력하세요: ");
int point = scanner.nextInt();
String userGrade = "";
if(point > VIP_POINT) {
userGrade = "VIP";
} else if(point > GOLD_POINT) {
userGrade = "GOLD";
} else if(point > SILVER_POINT) {
userGrade = "SILVER";
} else if(point > BRONZE_POINT) {
userGrade = "BRONZE";
} else {
userGrade = "GENERAL";
}
System.out.println("회원 등급: " + userGrade);
먼저 점수가 0~100 범위인지 검증하고, 정상 범위일 때만 A~F 등급을 계산했다.
이렇게 하면 예외 입력을 초기에 차단할 수 있다.
Scanner scanner2 = new Scanner(System.in);
System.out.print("점수를 입력하세요: ");
int score = scanner2.nextInt();
String grade = "";
if(score > 100 || score < 0) {
System.out.println("불가능한 점수 입력입니다.");
grade = "X";
} else {
if(score > 89) {
grade = "A";
} else if(score > 79) {
grade = "B";
} else if(score > 69) {
grade = "C";
} else if(score > 59) {
grade = "D";
} else {
grade = "F";
}
}
System.out.println("당신의 점수는 " + score + "점이고, 등급은 " + grade + "입니다.");
윤년 조건: (4의 배수 AND 100의 배수 아님) OR (400의 배수) 이다.
괄호로 조건 우선순위를 정확히 묶는 것이 중요했다.
Scanner scanner3 = new Scanner(System.in);
System.out.print("연도를 입력하세요: ");
int year = scanner3.nextInt();
String leapYear = "윤년입니다.";
if((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
// leapYear 유지
} else {
leapYear = "윤년이 아닙니다.";
}
System.out.println(year + "년은 " + leapYear);
조건식 ? 값1 : 값2 형태로 분기 결과를 한 줄로 만들 수 있다.
다만 중첩 삼항은 가독성이 떨어질 수 있어 필요한 경우만 사용한다.
String result3 = year < 0 ? "불가능한 연도입력입니다."
: ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
? "윤년입니다."
: "윤년이 아닙니다.";
System.out.println(year + "년은 " + result3);
값이 정해진 선택지(메뉴 번호 등)일 때 switch-case로 분기할 수 있다.
break를 안 쓰면 아래 case까지 이어질 수 있으니 주의한다.
int choice = 3;
switch(choice) {
case 1:
System.out.println("메뉴 1을 선택하였습니다.");
break;
case 2:
System.out.println("메뉴 2를 선택하였습니다.");
break;
case 3:
System.out.println("메뉴 3을 선택하였습니다.");
break;
default:
System.out.println("불가능한 메뉴 선택입니다.");
}
while은 조건이 true일 때 반복 실행된다.
무한루프를 막기 위해 언젠가 조건이 false가 되도록 변화를 설계해야 한다.
int i = 0;
while(i < 100) {
System.out.print(++i + " ");
if(i % 10 == 0) {
System.out.println();
}
}
바깥 while이 한 번 돌 때마다, 안쪽 while이 여러 번 도는 구조다.
안쪽 반복에서 사용한 변수는 바깥 반복이 한 사이클 끝날 때 초기화가 필요할 수 있다.
int day = 0;
while(day < 5) {
day++;
int period = 0; // 안쪽 while용 변수는 바깥 while마다 초기화
while(period < 3) {
period++;
System.out.println(day + "일차 " + period + "교시입니다.");
}
}
캐스팅은 단순히 “바꾸는 법”보다 왜 업캐스팅은 암시적이고
다운캐스팅은 명시적인지(데이터 손실 위험) 이해하는 게 핵심이었다.
조건문은 분기 순서가 전부고, 상수(final)로 기준값을 고정하면 코드가 훨씬 읽기 쉬워진다.
while은 조건이 false가 되는 시점을 직접 설계하지 않으면 무한루프가 된다는 점을 확실히 체감했다.