《Effective Java》阅读笔记10 始终要覆盖toString

1.为什么要覆盖toString方法?

public class Person {
		protected String name;
		protected int age;
 
 
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public int getAge() {
			return age;
		}
		public void setAge(int age) {
			this.age = age;
		}
		public Person(String name, int age) {
			super();
			this.name = name;
			this.age = age;
		}
		/*@Override
		public String toString() {
			return "Person [name=" + name + ", age=" + age + "]";
		}*/
		public static void main(String[] args) {
			Person s = new Person("liming", 6);
			System.out.println(s);
		}
	}

如果不覆盖打印:

demo6.Person@1636731

覆盖打印:

@Override
public String toString() {
    return "\nname: " + name + "\nage: " + age;}
Person [name=liming, age=6]

虽然java.lang.Object提供了toString方法的一个实现,但它返回的字符串通常并不是类的用户所期望看到的。

尽管有人认为“Person@1636731”算得上简洁和易于阅读,但是与“Person [name=liming, age=12]”比较起来,它还算不上信息丰富的。它包含类的名称,以及一个“@”符号,接着是散列码的无符号十六进制表示法,例如“Person@1636731”。

toString的约定进一步指出,建议所有的类都覆盖这个方法。

2、无论你是否指定格式,都要在文档中明确

  • 是否指定格式,都为toString 返回值中包含的信息,提供了一种编程式的访问路径
  • 无论与否,都请在文档中表明你的意图

toString()方法的通用约定是:返回当前对象“简洁,但信息丰富,并且易于阅读的表达形式”。

指定toString返回值的格式有不足之处:如果这个类已经被广泛使用,一旦指定格式,就必须始终如一地坚持这种格式。无论是否决定指定格式,都应该在文档中明确地表明意图。

3 Guava关于toString的

Guava通过 Objects.toStringHelper为我们提供了方便创建toString的方法。看下面的样例:

/ Returns "ClassName{x=1}"
   Objects.toStringHelper(this)
       .add("x", 1)
       .toString();

   // Returns "MyObject{x=1}"
   Objects.toStringHelper("MyObject")
       .add("x", 1)
       .toString();

Guava关于toString的文档连接https://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained

// 重写PhoneNumber的toString方法 - Effective Java中文第二版第44页

package org.effectivejava.examples.chapter03.item10;
import java.util.HashMap;
import java.util.Map;

import com.google.common.base.Objects;

public final class PhoneNumber {
        private final short areaCode;
        private final short prefix;
        private final short lineNumber;

        public PhoneNumber(int areaCode, int prefix, int lineNumber) {
                rangeCheck(areaCode, 999, "area code");
                rangeCheck(prefix, 999, "prefix");
                rangeCheck(lineNumber, 9999, "line number");
                this.areaCode = (short) areaCode;
                this.prefix = (short) prefix;
                this.lineNumber = (short) lineNumber;
        }

        private static void rangeCheck(int arg, int max, String name) {
                if (arg < 0 || arg > max)
                        throw new IllegalArgumentException(name + ": " + arg);
        }

        @Override
        public boolean equals(Object o) {
                if (o == this)
                        return true;
                if (!(o instanceof PhoneNumber))
                        return false;
                PhoneNumber pn = (PhoneNumber) o;
                return pn.lineNumber == lineNumber && pn.prefix == prefix
                                && pn.areaCode == areaCode;
        }

        @Override
        public int hashCode() {
                int result = 17;
                result = 31 * result + areaCode;
                result = 31 * result + prefix;
                result = 31 * result + lineNumber;
                return result;
        }

    //Effective Java原有的toString方法
        /*
         * @Override public String toString() { return
         * String.format("(%03d) %03d-%04d", areaCode, prefix, lineNumber); }
         */

        /**
         * 采用Guava实现的toString
         *
         */
        @Override
        public String toString() {
                return Objects.toStringHelper(this)
                                .addValue(String.format("(%03d) %03d-%04d", areaCode, prefix,lineNumber))
                                .add("areaCode", areaCode)
                                .add("prefix", prefix)
                                .add("lineNumber", lineNumber)
                                .toString();
        }

        public static void main(String[] args) {
                Map<PhoneNumber, String> m = new HashMap<PhoneNumber, String>();
                m.put(new PhoneNumber(707, 867, 5309), "Jenny");

                System.out.println(m);
        }
}

输出对比

//原输出
{(707)
867-5309=Jenny}

//Guava实现输出 
{PhoneNumber{(707) 
867-5309, areaCode=707, prefix=867, lineNumber=5309}=Jenny}

4.结论

覆盖toString就是为了调试或者打印的时候可以更直观的看到对象的有用的信息,所以建议写新写类的时候要覆盖toString方法。

5.参考文献

https://www.jianshu.com/p/05bf27bb2efc
https://www.javatt.com/p/6191
在这里插入图片描述

本公众号分享自己从程序员小白到经历春招秋招斩获10几个offer的面试笔试经验,其中包括【Java】、【操作系统】、【计算机网络】、【设计模式】、【数据结构与算法】、【大厂面经】、【数据库】期待你加入!!!

1.计算机网络----三次握手四次挥手
2.梦想成真-----项目自我介绍
3.你们要的设计模式来了
4.一字一句教你面试“个人简介”
5.接近30场面试分享

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

haikuotiankongdong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值