10.Always override toString
针对于java.lang.Object已经帮我们实现好了的toString方法,当我们自己定义出来的类使用这古老的toString方法的时候,通常不会返回给你一个比较满意的字符串
那这个字符串由什么组成呢?
首先是有一个类名,加上一个“@”的符号,然后加上这个类的hash code的无符号16进制表示
举个例子,比如上一篇关于HashCode的文章中的PhoneNumber类
那么它的hash code就是这个样子: PhoneNumber@163b91
在JavaSE6中对于toString方法的规范是这样说的:
"a concise but informative representation that is easy for a person to read"
大意为 简洁而不失可读性和信息的表现
对于“PhoneNumber@163b91”这样的形式来说,十分简洁,同时也具有一定的可读性,就是信息的表现略晦涩,难以理解
比起” (707) 867-5309 “ 上面形式的信息的表现力就弱了许多
那么JavaSE6想和我们说其实就是:
建议所有子类重写toString方法!
的确是个好的建议
需要注意的是,重写toString方法的重要性可能不会像我们之前说提过的equals和hashCode方法来的重要,但是,重写这个方法并且对这个方法做出一个漂亮的实现会让我们的类用起来更加的愉快,甚至说,优雅!
当一个类作为参数传递给println,printf,字符串的连接操作符,或者assert,被debugger打印啊之类的,就会自动地调用这个类的toString方法
printf是1.5之后才加进来的方法,依赖于String.format,这个方法就特别像C语言中的sprintf函数
如果你实现好了这个toString方法,那么你在打印一些调试信息的时候就特别的轻松,如下
System.out.println("Failed to connect: " + phoneNumber);
不管你是否重写了toString方法,程序员们都会试图像上面这样来打印调试信息,只不过,如果你好好的重写了该方法,那么这条信息就比你不重写的时候所产生的信息来的有用
重写一个好的toString方法不仅仅对本类产生作用,它还会延伸到那些拥有该类引用的那些对象的身上!
举个例子,比如说Collection这样的集合类,当你打印Map的时候你会更加愿意看到“ {Jenny=PhoneNumber@163b91} ”还是“ {Jenny=(707) 867-5309} ”呢?
实际应用中,toString方法需要返回该对象的所有的有意思的信息
正如我们之前提到的phoneNumber类,如果有这么一个集合包含了成千上万的phoneNumber,那么它应该返回一个概括性的描述,这个描述就类似于”Manhattan white pages (1487536 listings)“,这样的形式,而不是返回那么多条数据
理想条件下,我们希望返回的这个string应当是不言自明的
你还需要做的一个重要的事情就是,当你实现toString方法的时候,是否要在文档中指定返回值的格式
对于那些值依赖的类来说,比如电话号码,矩阵之类的,推荐的做法应该是在文档中指定返回值的格式,这样做的优点在于使得一个对象的表述变得标准,明确而且具有可读性,这样的表达可以被输入或者输出在人类可读的持久型数据对象中,比如说XML文档
如果你指定了返回值的格式,那么较好的做法是在类中添加静态工厂或者构造方法,这样利于程序的拓展之类的,这样的方法被应用在Java 平台库中,比如 BigInteger , BigDecimal 以及那些对基本类型的封装类
指定返回值格式的缺点在于,你的程序的灵活性将降低,也就是说你一旦重新改了这个格式,那么很多以往的程序就无法兼容了,这是我们需要好好考虑的
不管你打不打算指定返回值的格式,你都应该在文档中清楚地说明你的打算,举个例子:
/**
* Returns the string representation of this phone number.
* The string consists of fourteen characters whose format
* is "(XXX) YYY-ZZZZ", where XXX is the area code, YYY is
* the prefix, and ZZZZ is the line number. (Each of the
* capital letters represents a single decimal digit.)
*
* If any of the three parts of this phone number is too small
* to fill up its field, the field is padded with leading zeros.
* For example, if the value of the line number is 123, the last
* four characters of the string representation will be "0123".
*
* Note that there is a single space separating the closing
* parenthesis after the area code from the first digit of the
* prefix.
*/
@Override public String toString() {
return String.format("(%03d) %03d-%04d",
areaCode, prefix, lineNumber);
}
有了这些说明,在你的程序的基础上进行开发的人就不会因为格式修改而责怪你了
需要注意的是,你必须对toString返回的各类信息所在的域提供编程访问,这对于整个系统的构建有着极其重要的意义
网友评论