字符串被用来表示文本,他在这方面也确实做的很好。因为字符串很通用,并且java语言也支持得很好,所以自然就会有这样一种倾向:即使在不适合使用的字符串的场合,人们往往也会使用字符串。本篇文章就是讨论一些不应该使用字符串的情形。
字符串不适合代替其他类型 当一段数据从文件、网络、或者键盘设备,进入到程序中之后,他通常比字符串的形式存在。有一种自然的倾向是让他继续保留这种形式,但是,只有当这段数据本质上确实是文本信息时,这种想法才是合理的。如果他是数值,就应该转换为适当的数值类型,比如:int、float、BigDecimal类型。如果他是一个“是——或——否”这种问题的答案,就应该被转换为boolean类型,如果存在适当的值类型,不管是基本类型,还是对象引用,大多应该使用这种类型,如果不存在这种类型,就应该编写一个类型。虽然这条建议是显而易见的,但却经常遭到违反。
字符串不适合代替枚举类型 枚举类型比字符串更加适合用来表示枚举类型的常量.
字符串不适合代替聚集类型 如果一个实体有多个组件,用一个字符串来表示这个实体通常很不恰当的,例如,下面这行代码来源于真实的系统:
String compoundKey = className + "#" + i.next();
这种方法有许多缺点。如果用来分割域的字符串也出现在某个域中,结果就会出现混乱。为了访问单独的域,必须解析该字符串,这个过程非常慢,也很繁琐,还容易出错。你无法提供equals、toString或者compareTo方法,只好被迫几首String提供的行为。更好的做法是,简单的编写一个类来描述这个数据集,通常是一个私有的静态成员类。
字符串不适合代替能力表 有时候,字符串被用于某种功能进行授权访问。例如,考虑设计一个提供线程局部变量的机制。这个机制提供的变量在每个线程中都有自己的值。自从java1.2以后以来,lava类库就有提供线程局部变量机制,但是在那之前,程序员必须自己完成。几年前面对这样的设计任务时,有些人自己提出了同样的设计方案:利用客户提供的字符串键,对每个线程局部变量的内容进行访问授权。
public class ThreadLocal { private ThreadLocal(){} public static void set(String key,Object value){} public static Object get(String key){return key;} }
这种方法的问题在于。这些字符串键代表一个共享的全局命名空间。要是这种方法可行,客户端提供的字符串必须是唯一的:如果两个客户端各自决定为他们的线程局部变量使用同样的名称,他们实际上就无意中共享了这个变量,这样往往会导致两个客户端都失败。而且,安全性也很差,恶意的客户端可能有意的使用与另一个客户端相同的键,以便非法的访问其他客户端的数据。
要修正 这个API并不难,只要使用一个不可伪造的键来代替字符串即可:
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:
public final class ThreadLocal{ public ThreadLocal(){} public void set(Object value){} public Object get(){} }
这个API不是类型安全的,因为当你从线程局部得到它时,必须将值从Object转换成他的实际值,不可能使原始的基于String的API为类型安全的,要基于Key的API为安全的也很困难,但是,通过将ThreadLocal类泛型化,使这个API变成类型安全的就是很简单的事情了:
public final class ThreadLocal<T>{ public ThreadLocal(){} public void set(T value){} public T get(){} }
粗略的讲,这正是java.util.ThreadLocal提供的API,除了解决基于字符串的API的问题之外,与前面的两个基于API相比,他还是更快速、更优雅。
总而言之 如果可以使用更加合适的数据类型,或者可以编写更加合适的数据类型,就应该避免用字符串表示对象。若使用不当,字符串会比较其他类型更急笨拙、更加不灵活、速度更慢,也更容易出错。经常被错误的用字符来代替的类型包括基本类型、枚举类型和聚集类型。
相关推荐
因为字符串是如此常见,并且受到 Java 的良好支持,所以很自然地会将字符串用于其他目的,而不是它们适用的场景。要访问各个字段,你必须解析字符串,这是缓慢的、冗
Effective java 3 学习记录
《Effective Java》第三版中文版目录 第一章 介绍 1 第二章 创建和销毁对象 4 1 考虑用静态工厂方法替换构造器 4 2 当遇到多个构造器参
Effective Java读书笔记.pdf
effective java 读书笔记,第二版自己摘要并翻译,以备速查。
本书详细介绍企业级计算技术中的常见问题,并描述使用企业级Java平台技术处理这些问题的方法。本书以若干条建议、揸南的形式,言简意赅地介绍了J2EE开发中的微妙之处。无论你是否是Java开发人员,本书都将为你开发...
effective-java 自己用网上的翻译的html版本,生成的pdf版,仅供参考,仅供参考,仅供参考,仅供参考
Effective Java读书笔记,记载了大部分我觉的有用的东西,前半部分有代码说明,但后半部分的代码,太过琐碎,就没有整理
effective-java 配套代码
【Effective Java】阅读笔记markdown 文件
C++学习书籍——effective c++ 3rd(中英文)
Writing Effective Use Cases(编写有效用例)—— 完整中文版
15. 使类和成员的可访问性最小化 16. 在公有类中使用访问方法而非公有域 17.使可变性最小化:不可变类
《Effective Java》读书分享.pptx
Effective Java Effective Java Effective Java
Effective Arch Design——架构设计的10条经验(温昱)
Effective Enterprise Java
我尽我最大的可能为大家提供了一个最佳实践 —— 《effective java》 第三版。我希望第三版继续满足需求,同时继承前两版的精神。 Small is beautiful, but simple ain’t easy 。 蓝领不是贬低的意思,主要是 ...