Skip to content

Latest commit

 

History

History
125 lines (82 loc) · 3.68 KB

다른_타입이_적절하다면_문자열_사용을_피하라.md

File metadata and controls

125 lines (82 loc) · 3.68 KB

아이템 62 : 다른 타입이 적절하다면 문자열 사용을 피하라

1️⃣ 문자열은 다른 값 타입을 대신하기에 적합하지 않다.

> 받은 데이터가 수치형이라면?
int, float, BigInteger 등 적당한 수치 타입으로 변환해야 함

예, 아니오 질문의 답이라면?
적절한 열거 타입이나 boolean으로 반환해야 함

🌟 기본 타입이든 참조 타입이든 적절한 값 타입이 있다면 그것을 사용하고, 없다면 새로 작성하라!


2️⃣ 문자열은 열거 타입을 대신하기에 적합하지 않다.

상수를 열거할 때에는 문자열보다는 열거 타입이 월등히 나음 (아이템 34)


3️⃣ 문자열은 혼합 타입을 대신하기에 적합하지 않다.

String compoundKey = className + "#" + i.next();

> 두 요를 구분해주는 문자 #이 두 요소 중 하나에 쓰인다면 문제가 될 수 있음

> 요소를 개별로 접근하려면 문자열을 파싱해야 해서 느리고, 귀찮고, 오류 가능성이 커짐

> 적절한 equals, toString, compareTo 메서드를 제공할 수 없음

🌟 차라리 전용 클래스를 새로 만드는 편이 나음
🌟 이런 클래스는 보통 private 정적 멤버 클래스로 선언해야 함 (아이템 24)


4️⃣ 문자열은 권한을 표현하기에 적합하지 않다.

잠깐! ThreadLocal 이란?

👎 잘못된 예

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();
}

정리하자면!

🌟 더 적합한 데이터 타입이 있거나 새로 작성할 수 있다면, 문자열보다 그 타입을 사용하자.