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方法)。
其实关于拷贝复制,还有许多方法,这边暂时就写简单的,其它方法有点不懂,暂时就不写了