读书人

Cloneable 跟 clone()的总结和使用

发布时间: 2013-01-28 11:49:56 作者: rapoo

Cloneable 和 clone()的总结和使用
一.Cloneable 的用途
Cloneable和Serializable一样都是标记型接口,它们内部都没有方法和属性,implements Cloneable表示该对象能被克隆,能使用Object.clone()方法。如果没有implements Cloneable的类调用Object.clone()方法就会抛出CloneNotSupportedException。

二.克隆的分类
(1)浅克隆(shallow clone),浅拷贝是指拷贝对象时仅仅拷贝对象本身和对象中的基本变量,而不拷贝对象包含的引用指向的对象。
(2)深克隆(deep clone),深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。

举例区别一下:对象A1中包含对B1的引用,B1中包含对C1的引用。浅拷贝A1得到A2,A2中依然包含对B1的引用,B1中依然包含对C1的引用。深拷贝则是对浅拷贝的递归,深拷贝A1得到A2,A2中包含对B2(B1的copy)的引用,B2中包含对C2(C1的copy)的引用。

三.克隆的举例
要让一个对象进行克隆,其实就是两个步骤:
1. 让该类实现java.lang.Cloneable接口;
2. 重写(override)Object类的clone()方法。
Java代码:

  1. public class Wife implements Cloneable {
  2. private int id;
  3. private String name;
  4. public int getId() {
  5. return id;
  6. }
  7. public void setId(int id) {
  8. this.id = id;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public Wife(int id,String name) {
  17. this.id = id;
  18. this.name = name;
  19. }
  20. @Override
  21. public int hashCode() {//myeclipse自动生成的
  22. final int prime = 31;
  23. int result = 1;
  24. result = prime * result + id;
  25. result = prime * result + ((name == null) ? 0 : name.hashCode());
  26. return result;
  27. }
  28. @Override
  29. public boolean equals(Object obj) {//myeclipse自动生成的
  30. if (this == obj)
  31. return true;
  32. if (obj == null)
  33. return false;
  34. if (getClass() != obj.getClass())
  35. return false;
  36. Wife other = (Wife) obj;
  37. if (id != other.id)
  38. return false;
  39. if (name == null) {
  40. if (other.name != null)
  41. return false;
  42. } else if (!name.equals(other.name))
  43. return false;
  44. return true;
  45. }
  46. @Override
  47. public Object clone() throws CloneNotSupportedException {
  48. return super.clone();
  49. }
  50. /**
  51. * @param args
  52. * @throws CloneNotSupportedException
  53. */
  54. public static void main(String[] args) throws CloneNotSupportedException {
  55. Wife wife = new Wife(1,"wang");
  56. Wife wife2 = null;
  57. wife2 = (Wife) wife.clone();
  58. System.out.println("class same="+(wife.getClass()==wife2.getClass()));//true
  59. System.out.println("object same="+(wife==wife2));//false
  60. System.out.println("object equals="+(wife.equals(wife2)));//true
  61. }
  62. }
四.浅克隆的举例 Java代码:
  1. public class Husband implements Cloneable {
  2. private int id;
  3. private Wife wife;
  4. public Wife getWife() {
  5. return wife;
  6. }
  7. public void setWife(Wife wife) {
  8. this.wife = wife;
  9. }
  10. public int getId() {
  11. return id;
  12. }
  13. public void setId(int id) {
  14. this.id = id;
  15. }
  16. public Husband(int id) {
  17. this.id = id;
  18. }
  19. @Override
  20. public int hashCode() {//myeclipse自动生成的
  21. final int prime = 31;
  22. int result = 1;
  23. result = prime * result + id;
  24. return result;
  25. }
  26. @Override
  27. protected Object clone() throws CloneNotSupportedException {
  28. return super.clone();
  29. }
  30. @Override
  31. public boolean equals(Object obj) {//myeclipse自动生成的
  32. if (this == obj)
  33. return true;
  34. if (obj == null)
  35. return false;
  36. if (getClass() != obj.getClass())
  37. return false;
  38. Husband other = (Husband) obj;
  39. if (id != other.id)
  40. return false;
  41. return true;
  42. }
  43. /**
  44. * @param args
  45. * @throws CloneNotSupportedException
  46. */
  47. public static void main(String[] args) throws CloneNotSupportedException {
  48. Wife wife = new Wife(1,"jin");
  49. Husband husband = new Husband(1);
  50. Husband husband2 = null;
  51. husband.setWife(wife);
  52. husband2 = (Husband) husband.clone();
  53. System.out.println("husband class same="+(husband.getClass()==husband2.getClass()));//true
  54. System.out.println("husband object same="+(husband==husband2));//false
  55. System.out.println("husband object equals="+(husband.equals(husband)));//true
  56. System.out.println("wife class same="+(husband.getWife().getClass()==husband2.getWife().getClass()));//true
  57. System.out.println("wife object same="+(husband.getWife()==husband2.getWife()));//true
  58. System.out.println("wife object equals="+(husband.getWife().equals(husband.getWife())));//true
  59. }
  60. }

五.深克隆的举例
如果要深克隆,需要重写(override)Object类的clone()方法,并且在方法内部调用持有对象的clone()方法;注意如下代码的clone()方法Java代码:
  1. public class Husband implements Cloneable {
  2. private int id;
  3. private Wife wife;
  4. public Wife getWife() {
  5. return wife;
  6. }
  7. public void setWife(Wife wife) {
  8. this.wife = wife;
  9. }
  10. public int getId() {
  11. return id;
  12. }
  13. public void setId(int id) {
  14. this.id = id;
  15. }
  16. public Husband(int id) {
  17. this.id = id;
  18. }
  19. @Override
  20. public int hashCode() {//myeclipse自动生成的
  21. final int prime = 31;
  22. int result = 1;
  23. result = prime * result + id;
  24. return result;
  25. }
  26. @Override
  27. protected Object clone() throws CloneNotSupportedException {
  28. Husband husband = (Husband) super.clone();
  29. husband.wife = (Wife) husband.getWife().clone();
  30. return husband;
  31. }
  32. @Override
  33. public boolean equals(Object obj) {//myeclipse自动生成的
  34. if (this == obj)
  35. return true;
  36. if (obj == null)
  37. return false;
  38. if (getClass() != obj.getClass())
  39. return false;
  40. Husband other = (Husband) obj;
  41. if (id != other.id)
  42. return false;
  43. return true;
  44. }
  45. /**
  46. * @param args
  47. * @throws CloneNotSupportedException
  48. */
  49. public static void main(String[] args) throws CloneNotSupportedException {
  50. Wife wife = new Wife(1,"jin");
  51. Husband husband = new Husband(1);
  52. Husband husband2 = null;
  53. husband.setWife(wife);
  54. husband2 = (Husband) husband.clone();
  55. System.out.println("husband class same="+(husband.getClass()==husband2.getClass()));//true
  56. System.out.println("husband object same="+(husband==husband2));//false
  57. System.out.println("husband object equals="+(husband.equals(husband)));//true
  58. System.out.println("wife class same="+(husband.getWife().getClass()==husband2.getWife().getClass()));//true
  59. System.out.println("wife object same="+(husband.getWife()==husband2.getWife()));//false
  60. System.out.println("wife object equals="+(husband.getWife().equals(husband.getWife())));//true
  61. }
  62. }

但是也有不足之处,如果Husband内有N个对象属性,突然改变了类的结构,还要重新修改clone()方法。解决办法:可以使用Serializable运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。

参考java创建对象的第四种方法:
http://www.software8.co/wzjs/java/2881.html
读书人网 >编程

热点推荐