Java에서 조건을 비교할 때 주로 사용되는 두 가지는 if와 switch입니다. 각각의 조건문은 사용 용도가 다르며, 성능과 가독성 면에서 차이가 있어 취향이 타는 부분이 있습니다.
테스트 환경입니다.
if와 switch의 차이점과 함께, switch 문에서 JVM이 제공하는 최적화 기법인 Lookup Table과 Jump Table에 대해 알아보도록 하고 앞으로 조건문을 사용할 때 도움이 되었으면 좋겠습니다🎩
if 문은 논리적 조건을 비교할 때 사용됩니다. 각 조건은 불리언 값으로 조건이 참일 경우 해당 블록의 코드가 실행됩니다.
int number = 5;
if (number == 1) {
System.out.println("1");
} else if (number == 2) {
System.out.println("2");
} else {
if(number == 5) {
System.out.println("5");
}
System.out.println("Not 1 or 2");
}
if 문 사용 시점
단! 중첩 조건이 많아지면 가독성이 떨어짐과 동시에 단일 값 비교에서는 효율적이지 않을 수 있습니다🤗
switch 문은 주로 단일 값에 대해 여러 가능성을 비교할 때 사용되며, if-else 문보다 더 간결하고 가독성이 좋을 수 있습니다. switch는 정수, 문자열, enum과 같은 값의 비교에 적합합니다.
int number = 2;
switch (number) {
case 1:
System.out.println("1");
break;
case 2:
System.out.println("2");
break;
default:
System.out.println("Not 1 or 2");
}
switch 문 사용 시점
단! 복잡한 논리나 범위 조건 처리 불가하고 비교 대상이 정수, 문자열, enum으로 제한됩니다🤗
JVM은 switch 문을 최적화하기 위해 Lookup Table과 Jump Table이라는 두 가지 기법을 사용합니다. 이 방식은 switch 문에서 비교하는 값이 연속적인지 아닌지에 따라 결정됩니다.
연속적의 정의
switch 문에서 case 값들이 1, 2, 3, 4, 5처럼 연속적으로 나열된 경우가 해당됩니다. 일정한 간격이 있는 10, 20, 30 등도 연속적으로 보이지만 중간에 간격이 있기 때문에 해당 부분은 LookUpTable로 생성이 됩니다.
연속적이지 않은 값에서 사용되며 각 case 값과 해당 코드를 매핑하는 테이블 생성
예를 들어, 1, 5, 100과 같은 불연속적인 값을 처리할 때 JVM은 각 값에 대한 블록 주소를 저장한 테이블을 생성 후 이진탐색으로 LogN의 복잡도로 코드를 실행
예시)
해당 디렉토리에서 컴파일 후 javap 명령어로 디스어셈블한 코드를 확인
javac LookUpExample.java javap -c LookUpExample
lookupswitch가 생성된 걸 확인할 수 있습니다.
연속적인 케이스 값에서 사용되며 각 case 값에 대해 해당 블록으로 직접 점프하는 테이블 생성, O(1) 복잡도로 빠른 처리 가능
예시)
해당 디렉토리에서 컴파일 후 javap 명령어로 디스어셈블한 코드를 확인
javac JumpExample.java javap -c JumpExample
tableswitch로 jumpTable이 생성된 걸 볼 수 있습니다.
추가)
정수를 제외하고 enum도 연속적일 수 있는데 JVM은 각 enum 상수를 int 값으로 변환해 처리하며, 이를 통해 jumptable 방식으로 최적화가 가능합니다.
이마저도 enum의 속성을 switch문에서 중간에 하나 빼게되면 연속성을 잃어 LookUpTable로 생성되게 됩니다.
if와 switch는 각각 다른 용도와 장점이 있는것 같습니다.
취향차, 회사의 컨벤션 등 각자의 기준은 있었겠지만 어느정도 조건문을 선택하는데 있어 이 글을 통해 switch 문과 JVM의 최적화 방식에 대한 이해가 높아져 if문과 switch를 적재적소에 사용하는 기준을 잡는데 도움이 되었으면 좋겠습니다.🤗