Java中的Object类 (下篇)

版权声明:知识本无差别,何必在意你我? https://blog.csdn.net/qq_33774822/article/details/82993460

 要么读书,要么旅行,身体和心灵总有一个要在路上。——罗马假日

 上篇我们讲了hashCode和equals方法,首先我们先回顾一下

  1. hashCode是根据一定的规则和对象相关的信息映射成一个数值,这个数值成为散列值。他是由native关键字修饰的,native关键字主要是Java平台与本地C代码进行交互的API,即为Java Native Interface(JNI)。
  2. equals关键字是用来比较对象是否相等的。如果使用Object的equals方法,实际上比较的是两个对象的内存地址是否相同,这与我们的初衷往往不一样。我们常见的类型,如String,Integer,Long等,JDK都为我们重写了equals方法,所以我们可以直接使用equals方法来实现对象数值的比较。如果是我们自定义的对象,就要手动重写equals方法。

如有不明白,可以看我另外一篇文章哈。传送门来了,Java中的Object类 (上篇)

今天我讲clone方法,他的作用就是快速创建一个已有对象的副本,克隆后的对象类型与被克隆对象的类型相同。

咱先简单使用:

public class Person implements Cloneable {
  private String id;
  private String name;

  public String getId() {
    return id;
  }

  public void setId(String id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  @Override
  protected Person clone() throws CloneNotSupportedException {
    return (Person) super.clone();
  }
}
public class Test {
  public static void main(String[] args){
     Person person1=new Person();
     person1.setId("1");
     person1.setName("张三");
     System.out.println("修改前的person1:"+person1.getId()+","+person1.getName());
     try {
       Person person2=person1.clone();
       System.out.println("修改前的person2:"+person2.getId()+","+person2.getName());
       person2.setId("2");
       person2.setName("李四");
       System.out.println("修改后的person2:"+person2.getId()+","+person2.getName());
       System.out.println("修改后的person1:"+person1.getId()+","+person1.getName());
     }catch (Exception e){
       e.printStackTrace();
     }
  }
}

我们来看一下,这些代码到底干了啥呢。

首先Person类重写了clone方法,同时也抛出了cloneNotSupportedException这个异常,也就是说这个这个类不支持cloneable接口,就会抛出异常,这也就解释了Person实现了Cloneable接口。

其次我们看一下clone方法里面,也就是调用了父类Object的clone方法。

最后我们看一下测试类Test,先定义了一个person1对象,并为其赋值,id为1,name为张三,这第一行输出没啥问题。然后调用Person类的clone方法,实现赋值的功能,产生了person2对象,第二行输出也没问题。再修改了person2对象,id为2,name为李四,第三行也就输出了修改后的值。最后输出了person1对象的值。

这整个过程看下来,clone在这个过程中实现了深克隆,也就是person1和person2是两个完全不同的对象,他们互不干扰。

咱来试试复杂一点的,看代码咯

public class Clothes {
  private String color;
  private String size;

  public String getColor() {
    return color;
  }

  public void setColor(String color) {
    this.color = color;
  }

  public String getSize() {
    return size;
  }

  public void setSize(String size) {
    this.size = size;
  }

  public Clothes(String color, String size) {
    this.color = color;
    this.size = size;
  }
}
public class Person implements Cloneable {
  private String name;
  private Clothes clothes;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Clothes getClothes() {
    return clothes;
  }

  public void setClothes(Clothes clothes) {
    this.clothes = clothes;
  }

  public Person(String name, Clothes clothes) {
    this.name = name;
    this.clothes = clothes;
  }

  @Override
  public Person clone() throws CloneNotSupportedException {
    return (Person) super.clone();
  }
}
public class Test {
  public static void main(String[] args) {
    Person person1 = new Person("张三", new Clothes("红", "m号"));
    System.out.println("修改前的person1:name("+person1.getName()+"),clothes("+person1.getClothes().getColor()+","+person1.getClothes().getSize()+")");
    try {
      Person person2 = (Person) person1.clone();
      System.out.println("修改前的person2:name("+person2.getName()+"),clothes("+person2.getClothes().getColor()+","+person2.getClothes().getSize()+")");
      person2.setName("李四");
      person2.getClothes().setColor("蓝");
      person2.getClothes().setSize("l号");
      System.out.println("修改后的person2:name("+person2.getName()+"),clothes("+person2.getClothes().getColor()+","+person2.getClothes().getSize()+")");
      System.out.println("修改后的person1:name("+person1.getName()+"),clothes("+person1.getClothes().getColor()+","+person1.getClothes().getSize()+")");
    } catch (CloneNotSupportedException e) {
      e.printStackTrace();
    }
  }
}

这几个类描述了一个person类和clothes类,学生类中包括成员变量name和clothes。person类中重写了clone()方法,而clothes类并没有重写clone方法。

我们看一下运行结果,person2是由person1克隆过来的,所以输出语句的第一行和第二行,属性值是一样的。然后修改了person2的name值和clothes值,结果person1的name值没有改变,还是原来的张三,而clothes值并变成了蓝,l号。

这说明其实调用Object类的clone方法,是在内存上开辟一块和原始对象一样的空间,然后原样拷贝原始对象的内容,对于基本的数据类型来说,是没有对象的(就像刚才的示例一样,在修改完person2的name和clothes后,person1的name并没有改变,还是原来的张三)。但对于非基础类型来说,他保存的只是对象的引用(就像刚才的示例,在修改完person2的name和clothes后,person1的clothes发生了变化)。

解决方法:

将非基础类型也重写clone方法,实现引用克隆。至于代码,就在上面Clothes类里面加上重写的代码就ok啦,我就不写了哦。

猜你喜欢

转载自blog.csdn.net/qq_33774822/article/details/82993460
今日推荐