> 받은 데이터가 수치형
이라면?
int, float, BigInteger 등 적당한 수치 타입으로 변환해야 함
> 예, 아니오
질문의 답이라면?
적절한 열거 타입이나 boolean으로 반환해야 함
🌟 기본 타입이든 참조 타입이든 적절한 값 타입이 있다면 그것을 사용하고, 없다면 새로 작성하라!
상수를 열거할 때에는 문자열보다는 열거 타입이 월등히 나음 (아이템 34)
String compoundKey = className + "#" + i.next();
> 두 요를 구분해주는 문자 #
이 두 요소 중 하나에 쓰인다면 문제가 될 수 있음
> 요소를 개별로 접근하려면 문자열을 파싱해야 해서 느리고, 귀찮고, 오류 가능성이 커짐
> 적절한 equals, toString, compareTo 메서드를 제공할 수 없음
🌟 차라리 전용 클래스를 새로 만드는 편이 나음
🌟 이런 클래스는 보통 private 정적 멤버 클래스로 선언해야 함 (아이템 24)
public class ThreadLocal {
private ThreadLocal() {} //객체 생성 불가
// 현 스레드의 같은 값을 키로 구분해 저장한다.
public static void set(String key, Object value);
// (키가 가르키는) 현 스레드의 값을 반환한다.
public static Object get(String key);
}
> 만약 두 클라이언트가 같은 키를 사용한다면?
의도치 않게 같은 변수를 공유
결국 두 클라이언트 모두 제대로 기능하지 못하게 됨
> 보안에도 취약함
악의적인 클라이언트가 의도적으로 같은 키를 사용하여 다른 클라이언트의 값을 가져올 수 있음
Key 클래스로 권한을구분함
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는 더이상 스레드 지역변수를 구분하기 위한 키가 아님
> 그 자체가 스레드 지역변수가 됨
🌟 결과적으로 톱 레벨 클래스인 ThreadLocal 클래스는 별달리 하는 일이 없음
🌟 중첩 클래스 Key의 이름을 ThreadLocal로 변경
public final class ThreadLocal {
public ThreadLocal();
public void set(Object value);
public Object get();
}
> 타입 안전하지 않음
get으로 얻은 Object 를 형 변환해서 사용해야 함
🌟 매개변수화 타입(아이템 29)으로 선언하면 해결할 수 있음
// 매개변수화로 타입안전성 확보
public final class ThreadLocal<T> {
public ThreadLocal();
public void set(T value);
public T get();
}
🌟 더 적합한 데이터 타입이 있거나 새로 작성할 수 있다면, 문자열보다 그 타입을 사용하자.