Java7에 추가된 Java 언어의 7가지 개선사항 중 본 포스트에서는 "Strings in 'switch' statements"에 대해 정리하고, 몇 가지 주의사항에 대해 언급하겠습니다. 7가지 개선사항은 다음과 같습니다.(OpenJDK: "Project Coin", JSR-334)
- Binary Literals
- Underscores in Numeric Literals
- Strings in switch Statements
- The try-with-resources Statement
- Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking
- Type Inference for Generic Instance Creation
- Improved Compiler Warnings and Errors When Using Non-Reifiable Formal Parameters with Varargs Methods
Java7의 Language Specification에 기술된 switch 문장의 구문은 다음과 같습니다.
SwitchStatement: switch ( Expression ) SwitchBlockExpression에는 char, byte, short, int, Character, Byte, Short, Integer, String 그리고 enum 타입이 올 수 있으며, 기존에 허용되지 않던 String 타입이 추가되었습니다.
Java7 이전에는 switch 문장에서 String 타입 표현식을 허용하지 않았기 때문에 다중 if-else 문장으로 처리할 수 밖에 없었습니다.
public void withoutString(String str) { if(str.equals("bob") || str.equals("sam")) //do something ... else if(str.equals("carl") || str.equals("joy")) //do something ... else if(str.equals("anna") || str.equals("haron")) //do something ... else //do something ... }위 코드를 switch 문장으로 옮기면 다음과 같습니다.
public void withString(String str) { switch(str) { case "bob": case "sam": //do something ... break; case "carl": case "joy": //do something ... break; case "anna": case "haron": //do something ... break; default: //do something ... } }두 코드를 비교해 보면 if-else 문장의 경우 매번 String 클래스의 equals() 메서드로 문자열을 비교해야하는 번거로움이 있음을 알 수 있습니다.
개인적으로는 개선된 기능을 통해 코드의 가독성이 좋아졌다고 생각되나 주의해야 할 점이 있습니다.
- 표현식에 사용되는 String 객체가 null인지 확인해야 함
- String 비교시 대소문자 구분("Sam"과 "sam"은 다른 객체)
- 오직 String 타입의 참조변수만 허용
첫 번째 주의할 사항은 바로 표현식에 사용되는 str이 null인 경우입니다. if-else 문장에서 문자열을 비교하는 equals() 메서드 호출도 null.equals()는 NullPointerException에 해당합니다. 이러한 경우 null 문자열와의 비교는 항상 false를 반환하도록 다음과 같은 트릭을 사용하여 NullPointerException을 방지할 수 있습니다.
if("bob".equals(str) || ...
Java7의 switch 문장의 경우, 다음 코드와 같이 case문에서 null 상수를 사용할 수 없기때문에 적절한 전처리가 필요합니다.
switch(str) { case null: //ERROR!! ..... break; case "bob": case "sam": System.out.println("bob or sam"); break; default: System.out.println("default"); break; }
두 번째 사항은 문자열 객체의 대소문자 구분에 관한 내용이고, 마지막으로 오직 String 타입만 Expression에서 허용되므로 다음과 같은 코드는 컴파일에러입니다.
public void switchTest() { //OK: "bob" is-a Object!! Object str = "bob"; //ERROR!! switch(str) { ... } }
참고로 switch 문장에서 String 타입이 지원되기까지 대략16년 정도 걸렸다고 합니다. 1995년에 보고된 다음 Bug 리포트를 참조해 보시기 바랍니다.
[참고문헌]
1. Java Magazine 2011 Premiere
2. Java SE 7 Features and Enhancements
5 댓글
감사합니다
답글삭제잘 보았습니다.
답글삭제작성자가 댓글을 삭제했습니다.
답글삭제재밋네요 :D
답글삭제왜이렇게 늦게 지원하게 되었을까요?
기술적인 문제 vs 철학적인 문제
아니면 그냥 귀찮앗는지.. ㅎㅎ
예전보다 성능이 많이 좋아져서 trade-off 할 수 있게 된것 때문이 아닐까요?
삭제https://namocom.tistory.com/653