문자열을 쓰지 않아야할 사례
- 문자열은 다른 값 타입을 대신하기에 적합하지 않다
- 파일, 네트워크, 키보드 입력으로부터 데이터를 받을 때 주로 문자열을 사용한다.
- 입력 받을 데이터가 진짜 문자열일 때만 사용하는게 좋다.
- 받은 데이터가 수치형이라면 int, float, BigInteger등 적당한 수치 타입으로 변환해야 한다.
- 예/아니오 질문의 답이라면 적절한 열거타입이나 boolean으로 변환해야 한다.
- 문자열은 열거 타입을 대신하기에 적합하지 않다.
- 상수를 열거할 때는 문자열보다 열거 타입이 월등히 낫다.
- 문자열은 혼합 타입을 대신하기에 적합하지 않다.
- 여러 요소가 혼합된 데이터를 하나의 문자열로 표현하는 것은 대체로 좋지 않은 생각이다.
- 예시) String compoundKet = className + "#" + i.next();
- 두 요소를 구분하여 파싱하는 문자 #이 두 요소중 하나에서 쓰였다면 문제가 된다.
- 각 요소를 개별로 접근하려면 문자열을 파싱해야 해서 느리고, 귀찮고, 오류 가능성도 커진다.
- 적절한 equals, toString, compareTo 메서드를 제공할수 없으며, String이 제공하는 기능에만 의존해야 한다.
- 차라리 전용 클래스를 새로 만드는 편이 낫다.
- 문자열은 권한을 표현하기에 적합하지 않다.
- 권한을 문자열로 표시하면 의도치 않은 자원 공유가 이루어질 수 있다.
각 스레드가 자신만의 변수를 갖는 스레드 지역변수 기능을 설계한다고 했을 때 싱글턴 클래스를 만들어 static get, set 메서드로 key, value를 할당, 취득하는 방법으로 설계할 수 있다.
public class ThreadLocal {
private ThreadLocal() {} // 객체 생성 불가
// 현 스레드의 값을 키로 구분해 저장
public static void set(String key, Object value);
// (키가 가리키는) 현 스레드의 값을 반환
public static object get(String key);
}
이 방식의 문제는 스레드 구분용 키가 단순하게 문자열로 되어있어 의도치 않게 같은 키값을 사용하게 되면 이전 value 값이 덮이거나 값이 공유되어 보안에도 취약하다.
문자열 대신 위조할 수 없는 키를 사용하면 해결 된다. 이 키를 권한(capacity)라고도 한다.
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);
}
이 바 ㅇ법은 앞서 문자열 기반 API 문제가 해결되지만 개선점으로 set, get 메서드가 static 메서드일 이유가 없으니 Key 클래스의 인스턴스 메서드로 바꾼다.
이렇게 하면 Key는 더이상 스레드 지역변수를 구분하기 위한키가 아니라 그 자체가 스레드 지역변수가 된다.
결과적으로 지금 톱레벨 클래스인 ThreadLocal은 하는일이 없어지므로 중첩클래서 Key클래스의 이름을 ThreadLocalfh 바꾸면
public final class ThreadLocal{
public ThreadLocal();
public void set(Object value);
public Object get();
}
확장하여 사용할 수 없도록 final 클래스로 만들고 getKey() 고유키 생성을 생성자 자체로 만든다.
get()메서드는 사용한 곳에서 생성한 ThreadLocal 인스턴스를 반환할 것이다.
이 인스턴스가 key가 되는것
이 API 마지막 문제점은 get() 으로 얻은 Object를 매번 형변환 해야한다는 것인데
public final class ThreadLocal<T>{
public ThreadLocal();
public void set(T value);
public <T> get();
}
ThreadLocal을 매개변수화 타입으로 선언하면 간단하게 문제가 해결된다.
핵심정리
더 적합한 데이터 타입이 있거나 새로 작성할 수 있다면 문자열을 쓰고 싶은 유혹을 뿌리쳐라.
문자열은 잘못 사용하면 번거롭고, 덜 유연하고, 느리고, 오류 가능성도 크다.
문자열을 잘못 사용하는 흔한 예로는 기본타입, 열거타입, 혼합타입이 있다.
'개인룸 > 도윤' 카테고리의 다른 글
Item64. 객체는 인터페이스를 사용해 참조하라 (0) | 2023.08.21 |
---|---|
Item63. 문자열 연결은 느리니 주의하라 (0) | 2023.08.21 |
Item61. 박싱된 기본 타입보다는 기본 타입을 사용하라 (0) | 2023.08.08 |
Item60. 정확한 답이 필요하다면 float과 double은 피하라 (0) | 2023.08.07 |
Item58. 전통적인 for 문보다는 for-each 문을 사용하라 (0) | 2023.07.30 |