EffectiveJava学习笔记7:始终要覆盖toString、谨慎覆盖clone

1.始终要覆盖toString

个人理解:toString就是当把某一对象作为字符串输出时会调用这个方法。(比如:printf(xx);  "a"+xx;),其实际上都可看成为printf(xx.toString());  "a"+xx.toString();

Object虽然有提供toString,但其输出格式是以下形式的(类名@散列码的无符号16进制)

public String toString() {
        return this.getClass().getName() + "@" + Integer.toHexString(this.hashCode());
    }

虽然这个可以简要表达类,但是往往我们需要类内部属性的表现。比如(name=“沙丁鱼flat”),这样的内部信息。

所以在实际开发中,toString方法应该返回对象中包含的所有值得关注的信息,所以需要重写(覆盖)。

注意:如果toString是否使用自己的格式,来进行格式化输出(String.format之类的),不适用格式化的话最好文档注释部分有指示信息。(PS:在静态工具类或大部分枚举类型中重写toString是没有意义的)

 

2.谨慎覆盖clone

clone相当于复制对象,生成对象的副本,对象和副本两者初始时是一样的,但后面修改是各自独立的。

这也是赋值无法做到的,因为对象赋值是对象引用,这种是两者都指向同一对象实例的。

使用clone

1.使用Obejct的clone方法的前提是使对象拥有Cloneable接口:

”这个接口的作用的是作为对象的一个mixin接口,允许对象进行克隆(clone),这是因为Obejct的clone方法是受保护的,所以需要有这个接口改变超类中所保护方法的行为

2.由于可以允许重写clone方法了, 所以可直接重写为一个公有的clone方法:

public class tests implements Cloneable {
    @Override
    public tests clone() {

    }

}

3.重写clone方法的通用约定:

x.clone()!=x;   对象和副本各自独立

x.clone().getClass()==x.getClass();   对象和副本的类是相同的

x.clone().equals(x)返回true     克隆后的初始值两者是想用的

注意:不可变的类不应该提供clone方法,不必要。

4.重写clone方法

    @Override
    public tests clone() {
        try{
            return (tests) super.clone();
        }catch (CloneNotSupportedException e){
           throw new AssertionError();
        }
    }

CloneNotSupportedException 是受检异常。比如没写Cloneable接口,就会抛出这个异常。

5.注意类中的域(浅拷贝和深拷贝)

在重写clone方法前就需要注意了:类中的域(也就是属性),是否包含可变的对象。

public class tests implements Cloneable {
    public String a;
    public String b;
    public Activity activity;
    @Override
    public tests clone() {
        try{
            return (tests) super.clone();
        }catch (CloneNotSupportedException e){
           throw new AssertionError();
        }
    }

比如上图,如果进行a,b这两个属性,那么是没有问题的,但这里加上了一个自定义类Activity,属于可变对象就有问题了。

因为单纯这样重写的clone方法,克隆后的副本和原对象的activity还是引用同一个activity,因为这个还是没独立拷贝的。

所以这就引出一个概念:

浅拷贝:被复制对象的所有值属性都含有与原来对象的相同,而所有的对象引用属性仍然指向原来的对象。

深拷贝:在浅拷贝的基础上,所有引用其他对象的变量也进行了clone,并指向被复制过的新对象。

    public String a;
    public String b;
    public Activity activity;
    @Override
    public tests clone() {
        try{
            tests obj=(tests) super.clone();
            Activity a=obj.getActivity();
            obj.setActivity((Activity)a.clone());
            return obj;
        }catch (CloneNotSupportedException e){
           throw new AssertionError();
        }
    }

上图就是深拷贝的案例:在拷贝基本类型的同时,同时调用可变对象的拷贝方法,拷贝新的可变对象(所以深拷贝的时候,可变对象的类也要写Cloneable接口,然后重写clone方法)。

其实关于拷贝复制,还有许多方法,这边暂时就写简单的,其它方法有点不懂,暂时就不写了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值