Item62. 다른 타입이 적절하다면 문자열 사용을 피하라!
Intro
- 문자열(String)은 텍스트를 표현하도록 설계되었다.
- 그런데 문자열은 워낙 흔하고 자바가 잘 지원해주는 바람에 원래 의도대로 쓰이지 않는 경향이 있다.
문자열을 쓰지 않아야 할 상황
1. 문자열은 다른 값 타입을 대신하기에 적합하지 않다.
- 많은 사람들이 파일, 네트워크, 키보드 입력으로부터 데이터를 받을 때 주로 문자열을 사용하는데, 입력받을 문자열이 진짜 문자열일 때만 그렇게 하는 것이 좋다.
- 받은 데이터가 수치형이라면 int, float, BigInteger 등 적당한 수치 타입을 사용하고, ‘예/아니오’일 경우 열거 타입이나 boolean 타입을 사용하자.
- 즉, 기본 타입이든 참조 타입이든 적절한 값 타입이 있다면 그것을 사용하고, 없다면 새로 타입을 작성해 사용하자.
2. 문자열은 열거 타입을 대신하기에 적합하지 않다.
- 상수를 열거할 때는 문자열보다는 열거 타입이 월등히 낫다. 이는 아이템 34에서 다뤘다.
3. 문자열은 혼합 타입을 대신하기에 적합하지 않다.
- 여러 요소가 혼합된 데이터를 하나의 문자열로 표현하는 것은 대체로 좋지 못하다.
- 이렇게 여러 요소를 혼합해서 사용한다면, 각 요소를 파싱하기 위해 구분자를 설정하는데, 만역 여러 요소에서 구분자와 중복된 값이 포함되어 있다면 파싱에 오류를 겪을 수도 있다.
- 이러한 경우엔 차라리 전용 클래스를 새로 만드는 편이 낫다. 보통 이런 클래스를 private 정적 메서드로 선언한다.
4. 문자열은 권한을 표현하기에 적합하지 않다.
권한(capacity)을 문자열로 표현하는 경우가 종종 있는데, 이러면 문제가 생길 수 있다.
문자열로 스레드 지역변수 기능의 권한을 관리하는 예시다.
1 2 3 4 5 6 7 8 9
public class ThreadLocal { private ThreadLocal() { } // 객체 생성 불가 // 현 스레드의 값을 키로 구분해 저장한다. public static void set(String key, Object value); // (키가 가리키는) 현 스레드의 값을 반환한다. public static Object get(String key); }
- 클라이언트가 제공한 문자열을 키로 스레드별 지역변수를 식별한다.
- 이 방식의 문제는 스레드 구분용 문자열 키가 전역 이름공간에서 공유된다는 점이다.
- 만약 각 클라이언트가 소통하지 못해 같은 키 값을 사용한다면? 두 클라이언트 모두 제 기능을 하지 못할 것이다.
- 보안에 취약하다.
- 문자열 대신 위조할 수 없는 키를 사용하면 해결된다. 이러한 키를 권한(capacity)이라 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
public class ThreadLocal { private ThreadLocal() { } // 객체 생성 불가 public static class Key { // (권한) Key() { } } // 위조 불가능한 고유 키를 생성한다. public static Key getKey() { return new Key; } public static void set(Key key, Object value); public static Object get(Key key); }
- 앞서의 문제 두 가지를 모두 해결했지만, set, get은 이제 정적 메서드일 필요가 없으니 Key의 인스턴스 메서드로 바꾼다.
- 이렇게 하면 Key는 더 이상 스레드 지역변수를 구분하기 위한 키가 아니라, 그 자체가 스레드 지역변수가 된다.
1 2 3 4 5 6
// Key -> ThreadLocal public final class ThreadLocal { public ThreadLocal() { } public void set(Object value); public Object get(); }
- ThreadLocal은 별달리 하는 일이 없어지므로 치워버린다.
- 중첩 클래스 Key의 이름을 ThreadLocal로 바꾼다.
1 2 3 4 5
public final class ThreadLocal<T> { public ThreadLocal(); public void set(T value); public T get(); }
- 매개변수화 타입을 사용해 형변환의 안전성을 부여한다.
핵심 정리
- 더 적합한 데이터 타입이 있거나 새로 작성할 수 있다면, 문자열을 사용하지 말자.
- 문자열을 잘못 사용하면 번거롭고, 덜 유연하고, 느리고, 오류 가능성도 크다.
- 문자열을 잘못 사용하는 흔한 예로는 기본 타입, 열거 타입, 혼합 타입이 있다.
Comments powered by Disqus.