字符串设计的目的就是表示文本,但是有不应该使用字符串的情景:
1.字符串不适合代替其他的数值类型。
当一段数据从文件、网络,或者键盘设备,进入程序中后通常以字符串形式存在,有种倾向是让它继续保持字符串,但只有数据的本质是文本的时候,这种想法才算是合理的。
如果是数值,就应该被转化为对应的数值类型;
如果是是-否这种问题的答案,那么就应该转化为boolean类型;
如果存在恰当的值类型,那么不管是基本类型,还是对象引用,大多应该使用这种类型;
如果不存在这样的类型,那么就要编写这样的一个类型。
2.字符串不适合代替枚举类型
枚举类型比字符串更适合用来表示枚举类型的常量。
3.字符串不适合代替聚合类型
如果一个实体有多个组件,用一个字符串来表示这个实体是很不恰当的.
案例如下:标识符的名称已经被修改.
String compoundKey = className + "#" +i.next();
缺点:
a.如果用来分割域的字串出现在某个域中,结果就会发生混乱[意思是className或者i.next()中出现”#”]。
b.如果访问单独的域,必须解析字符串,过程非常慢,很繁琐易错。
c.无法使用equals,toString或者compareTo方法,只有被迫接受String提供的方法。
d.更好的做法是,简单地编写类描述这个数据集,通常使用私有的静态成员类。
4.字符串不适合代替能力表。
有时候,字符串被用于对某种功能进行授权访问,考虑设计一个提供线程局部变量的机制,这个机制提供的变量在每个线程中都有自己的值。
public class ThreadLocal {
privateThreadLocal() {}
public static void set(String key, Object value);
public static Object get(String 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);
}
虽然解决基于字符串API的问题,但实际上可以使用ThreadLocal本身作为键,就不再需要额外的键了。java.util.ThreadLocal提供的API正是这样的:
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);//将自身作为键来取得线程局部变量值
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
总之,如果可以使用更加合适的数据类型,或者可以编写更加合适的数据类型,那么就应该避免使用字符串来代替对象。
如果使用不当,字符串会比其他类型更加笨拙,不灵活,速度更慢,容易出错,经常被错误地用字符串代替的类型由基本类型,枚举类型和聚合类型。