您的位置:首页 > 编程语言 > Java开发

Java的clone机制及其重要的可变类与不可变类要义

2008-05-03 17:20 267 查看
当方法中传递的参数是基本数据类型时,采用的是值传递;当输入参数是对象时,采用的是引用传递。这是“影子克隆(shallow clone)”。如果想要按值传递参数,该类就要实现cloneable接口,并实现clone方法,将“对象名.clone()”做参数传递(deep clone)。
Object 类有 clone() 方法: protected native Object clone() throws CloneNotSupportedException;
该方法是 protected 的,显然是留待被子类 override 的。该方法又是 native 的,必然做了与具体平台相关的底层工作。
事实上,类 Object 的 clone() 方法首先会检查 this.getClass() 是否实现了 Cloneable 接口。 Cloneable 只是一个标志接口而已,用来标志该类是否有克隆功能。
public interface Cloneable {
}
如果 this.getClass() 没有实现 Cloneable 接口, clone() 就会抛 CloneNotSupportedException 返回。否则就会创建一个类型为 this.getClass() 的对象 other ,并将 this 各 field 的值赋值给 other 的对应 field ,若是基本数据类型及非可变类类型的field则是按值,若可变类类型则按引用赋值,然后返回 other 。

所谓不可变类,是指当创建了这个类的实例后,就不允许修改它的属性值。 它包括:
primitive变量: boolean,byte, char, double ,float, integer, long, short
jdk的不可变类:jdk的java.lang包中 Boolean, Byte, Character, Double, Float, Integer, Long, Short, String
可变类,是当你获得这个类的一个实例引用时,你可以改变这个实例的内容。 可变类对象间用“=”赋值,则会是使两个对象实际上会引用同一个实例。所以,只有实现深度clone才能使可变类对象的修改不影响原始对象的值。然而,对于不可变类,可变类的特性也是很有意义的,有的时候我们不希望重复创建相同的内容的实例。因此,我们也可以利用不可变类获得实例缓存。如:

Integer a=Integer.valueOf(10);
Integer b= Integer.valueOf(10);
则只会在第一次创建取值为10的Integer对象。也就是说a和b指向同一处内存上的内容。

那应该如何创建一个自己的不可变类:
·所有成员都是private
·不提供对成员的改变方法,例如:setXXXX
·确保所有的方法不会被重载。手段有两种:使用final Class(强不可变类),或者将所有类方法加上final(弱不可变类)。
·如果某一个类成员不是原始变量(primitive)或者不可变类,必须通过在成员初始化(in)或者get方法(out)时通过深度clone方法,来确保类的不可变。
反言之,任何提供了外部可修改途径的自定义类都是可变类。因而,只有实现深度clone才能使可变类对象按值赋给另一个对象,而不是按引用。例如,在自定义的类 A 中,假设用户声明一个不可变类 B 的field,并提供了可修改 B 值的途径。显然,A便因此成为一个可变类,尽管它包括有不可变类的字段,或者根本没有可变类的字段。

参考:
孙卫琴,《JAVA面向对象编程》,2006年版
Roger Tu,《Java Clone机制》,2007年3月,http://www.blogjava.net/RogerTwain
冠林,《可变类和不可变类(Mutable and Immutable Objects)》,2007年9月http://hi.baidu.com/%D5%C5%B9%DA%C1%D6/blog/item/f0aaa8af98eaafcf7cd92ab3.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: