【问题标题】:Shallow cloning in java : String and Object showing different behavioursjava中的浅克隆:显示不同行为的字符串和对象
【发布时间】:2014-07-14 17:54:26
【问题描述】:

问题基于以下代码:

class Car implements Cloneable
{
//Relevant constructor
     String name;
     int wheels;
     Car another;

 public Object clone()
 {
    /*DEEP
  Car n = new Car(this.name,this.wheels);
    n.another = new Car(this.another.name,this.another.wheels);
    return n;
*/ 

 return super.clone() ;
 }
}

main(String[] args) 
{
      Car c1 = new Car("merc",4);
      c1.another = new Car("baby merc",55);
      Car c2;
      c2 = (Car)c1.clone();

          //PART 1
          //HERE I TRY TO CHANGE object c2's another's name to "Han"
          System.out.println(c1.another.hashCode() == c2.another.hashCode());
/*POINT 1*/   c2.another.name  = "Han"; 
          System.out.println(c1.another.hashCode() == c2.another.hashCode());

          //PART 2
          String s = new String("gG");
          System.out.println(s.hashCode());
          s ="JAJA";
          System.out.println(s.hashCode());
}
  • 在第 1 部分中,我更改了对象 c1 的成员 another 的成员名称 与众不同。
  • 在第 2 部分中,我创建了一个字符串,检查其哈希码,然后更改其值,然后再次检查其有代码。

输出:

true
true
3264
2269358
  1. 我不明白当我更改c2.another.name 然后 c1.another.name 也指向前一个字符串“baby merc”所占用的完全相同的旧位置。 POINT1 处的操作不应该导致返回新的参考位置,从而导致c2.another 指向新位置而c1.another 指向旧位置吗?
  2. 为什么当我将一个字符串指向一个新的 细绳?分配了堆中的新区域并引用变量 保存新位置的引用。在c1c2 的情况下 即使修改后参考位置也不会改变!为什么?

【问题讨论】:

  • 车内的车?
  • 可能被拖走?
  • 请显示clonehashCode 方法(如果它们被覆盖)。
  • @Henry hashCodeclone 未被覆盖。这是一个浅克隆。所以我只是在clone() 方法中返回super.clone()
  • 请不要以改变其含义的方式更改问题。

标签: java string cloning


【解决方案1】:

c2 = (汽车)c1.clone(); // c1.another == c2.another(是的,引用是相等的,所以我用==)

我不明白,当我更改 c2.another.name 时,c1.another.name 也指向与前一个字符串“baby merc”所占用的完全相同的旧位置。 POINT1 处的操作不应该导致返回新的参考位置,从而导致 c2.another 指向新位置而 c1.another 指向旧位置吗?

c1 和 c2 共享相同的 another 对象/引用。他们关心其中的变化。第二行返回true,因为您正在更改another 中的某些内容,假设您有一盒硬币,两个人拿着它。如果您从中取出 2 个硬币,那么持有它的双方 人剩余的硬币将是相同的。

为什么当我将一个字符串指向一个新字符串时不会发生同样的情况?在堆中分配了一个新区域,并且引用变量保存了新位置的引用。在 c1 和 c2 的情况下,即使修改后参考位置也不会改变!为什么?

您正在创建 2 个不同的对象并为其创建相同的引用点(一个接一个),因此您有 2 个不同的哈希码。这与克隆无关。

【讨论】:

  • “更改后的哈希码 [...] 将与第一个不同”:不,不会。
  • @Henry - 哎呀.. 对不起.. 你是对的,除非他覆盖 hashCode,否则我不能这么说..
  • hashCode 根据 cmets 不会被覆盖。
  • @Henry - 是的......这就是为什么我删除了说明它会有所不同的部分...... :)
  • @Dubby 我猜Car 构造函数不会为name 分配新字符串,而只是分配传入的值。因此c1.namec2.name 又是完全相同的字符串实例。
【解决方案2】:

c1.anotherc2.another 是同一个对象,因此它们将始终具有完全相同的哈希码。

此外,标准哈希码是基于对象身份的。更改对象的字段不会更改其哈希码。

【讨论】:

    【解决方案3】:

    每当对包含任何类类型成员的对象调用 clone() 方法时,只会复制这些成员的引用变量。

    这就是为什么在执行以下语句时:

    c2 = (汽车)c1.clone();

    在 c2 的堆中创建了一个新对象,它包含对另一个对象的引用。 C1 还包含对另一个的引用。现在 c1 和 c2 都有指向另一个的引用变量。因此 c1 和 c2 都可以修改另一个的状态。

    对于String的情况,在堆中分配一个新的区域,

    1. 每当您使用“new”关键字创建字符串对象时

    2. 当你创建了一个字符串字面量,而该字符串目前在字符串池中不存在。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-17
      • 1970-01-01
      • 1970-01-01
      • 2012-07-02
      • 1970-01-01
      • 1970-01-01
      • 2011-08-14
      • 2021-05-23
      相关资源
      最近更新 更多