본문 바로가기

JAVA/Effective Java

item 62) 다른 타입이 적절하다면 문자열 사용을 피하라

728x90

문자열은 텍스트를 표현하도록 설계되었고, 자바에서도 잘 지원해줘서 다른 용도로 쓰이는 경우가 있음

 

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

-  파일, 네트워크, 키보드 등으로부터 입력을 받을때 주로 문자열 타입으로 받는다. 그후에 타입을 명시적으로 변환한다.

=> 타입을 명시적으로 변환하는 것은 좋은 프로그래밍 코드가 아님.(ClassTypeException 및 변환 코드로 기존 코드가 더러워진다.)

- 적절한 타입이 있다면 그 타입을을 사용하고 만약 없다면 새로운 타입을 작성하라.

 

2) 열거타입을 대신하기 어렵다. 

- 상수를 열거할떄는 열거타입을 사용하자.(변수의 범위를 제한할수 있다.)

 

3) 혼합타입을 대신하기 어렵다.

- 여러 요소가 혼합된 데이터를 하나의 문자열로 표현하는 것은 좋지 않다.

 

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

- className, i.next()에 구분자 #이 포함될경우 혼란스러워진다.

- 각 요소를 개별로 접근할 경우 문자열을 따로 파싱해줘야한다. 

- String이 제공하는 메서드에만 의존해야한다.(equals, toString, hashCode, compareTo 등)

 

4) 권한을 표현하기에 적합하지않다.

 

public class ThreadLocal {
    private ThreadLocal() {} //객체 생성 불가
    
    // 현 스레드의 값을 키로 구분해 저장한다.
    public static void set(String key, Object value);
    
    // (키가 가르키는) 현 스레드의 값을 반환한다.
    public static Object get(String key);
}

 

- 쓰레드를 String 타입 키로 구분한다. (클라이언트가 의도치 않게 같은 키를 사용한다면? 같은 변수를 공유하게 된다.)

- 악의적인 클라이언트가 같은 키를 사용한다면?

 

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

 

- setter, getter은 이제 정적 메서드일 필요가 없다. => Key의 인스턴스 메서드로 바꾼다.

- Key는 스레드 지연변수를 구하기 위한 키가 아니라 그 자체로 스레드변수가 된다.(Key가 ThreadLocal 역할을 대신한다.)

 

public final class Key<T> {
    public Key();
    public void set(T value);
    public T get();
}
//Object를 타입 변환하는 것이 아니라 제네릭한 매개변수 클래스로 만든다.