java对象赋值问题

本文通过两个示例对比,详细解析了Java中对象传递时容易出现的问题,特别是当对象在循环内部与外部创建时的不同行为及其原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天写程序,发现经常容易犯的问题,就是java对象传值问题,如以下两端代码:

Model model=new Model();
model.setModelName(modelName);
model.setIndex(preModelNumber);
preModelNumber++;

List<ViewPoint> temp=new ArrayList<>();

for(int i=0;i<Points.size();i++){
    ViewPoint vp=new ViewPoint();
    vp.setOrder(Points.get(i).getOrder());
    vp.setAbsX(Points.get(i).getAbsX());
    vp.setAbsY(Points.get(i).getAbsY());
    vp.setAbsZ(Points.get(i).getAbsZ());
    temp.add(vp);
}
model.setPoints(temp);
fieldModelXml.getItemModel().add(model);
Model model=new Model();
model.setModelName(modelName);
model.setIndex(preModelNumber);
preModelNumber++;

List<ViewPoint> temp=new ArrayList<>();
ViewPoint vp=new ViewPoint();

for(int i=0;i<Points.size();i++){
    vp.setOrder(Points.get(i).getOrder());
    vp.setAbsX(Points.get(i).getAbsX());
    vp.setAbsY(Points.get(i).getAbsY());
    vp.setAbsZ(Points.get(i).getAbsZ());
    temp.add(vp);
}
model.setPoints(temp);
fieldModelXml.getItemModel().add(model);
表面只是vp定义在里外的区别,但是实际上完全不同效果,第一段代码每次循环,vp都会销毁重新创建,不会出现赋值同一对象问题。而第二段
代码循环中,vp没有被销毁,最后的结果就是所有的tem中都被赋值了vp的引用,最后所以temp中的值都为循环最后一个赋值,导致不想要的结果。这一点要多注意
### Java对象赋值的原理 在 Java 编程语言中,当涉及到对象赋值时,存在三种主要的方式:直接赋值、浅拷贝以及深拷贝。这些方式的核心在于如何处理对象及其内部的数据结构。 #### 1. **直接赋值** 直接赋值是指将一个对象的引用传递给另一个变量。这种方式并不会创建新的对象实例,而是让两个变量指向同一个堆内存地址中的对象。因此,如果通过其中一个变量修改了该对象的状态,则另一变量也会反映出这种变化[^1]。 ```java class Example { int value; } Example obj1 = new Example(); obj1.value = 10; Example obj2 = obj1; // 直接赋值 obj2.value = 20; System.out.println(obj1.value); // 输出 20 ``` 上述代码展示了直接赋值的行为特点——`obj1` 和 `obj2` 实际上共享同一份底层数据[^2]。 --- #### 2. **浅拷贝 (Shallow Copy)** 浅拷贝会创建一个新的对象实例,但是仅复制原始对象中的基本数据类型字段或者对其他对象的引用本身(而非其实际内容)。换句话说,在浅拷贝的情况下,虽然目标对象是一个独立的对象,但如果它包含了某些复杂类型的成员变量(比如数组或其他类),那么这些成员仍然会被多个对象所共享。 实现方法通常可以借助于克隆接口 (`Cloneable`) 来完成: ```java import java.util.Arrays; class ShallowCopyExample implements Cloneable { int[] array; public ShallowCopyExample(int size) { this.array = new int[size]; Arrays.fill(this.array, 5); } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); // 默认执行的是浅拷贝逻辑 } } try { ShallowCopyExample original = new ShallowCopyExample(3); ShallowCopyExample copy = (ShallowCopyExample) original.clone(); System.out.println(Arrays.toString(original.array)); // [5, 5, 5] copy.array[0] = 99; // 修改副本中的数组元素 System.out.println(Arrays.toString(copy.array)); // [99, 5, 5] System.out.println(Arrays.toString(original.array)); // [99, 5, 5], 发现原对象也被改变了 } catch (CloneNotSupportedException e) {} ``` 可以看到,尽管我们调用了 `clone()` 方法来生成了一个新对象,但由于只是简单地复制了数组的引用而不是真正重新分配了一块存储空间用于保存相同数值序列的新数组,最终导致两者之间产生了相互依赖关系。 --- #### 3. **深拷贝 (Deep Copy)** 相比之下,深拷贝不仅创建了一个全新的对象,而且还会递归地对该对象内的每一个可变组件都进行单独的复制操作,从而确保源对象与目标对象完全隔离无任何关联[^3]。要达成此目的,一般有两种途径可供选择: - 手动编写自定义构造器; - 或者利用序列化机制自动完成整个过程。 以下是采用手动方式的一个例子: ```java class DeepCopyExample { private int[] values; public DeepCopyExample(int length) { this.values = new int[length]; Arrays.fill(values, 7); } public DeepCopyExample(DeepCopyExample another) { this(another.values.length); for (int i = 0; i < values.length; ++i) this.values[i] = another.values[i]; // 显式逐项复制 } } ``` 这样做的好处是可以彻底断开两者的联系,即使一方发生了改变也不会波及到另外一边。 --- ### 总结 综上所述,理解并掌握这三类不同的赋值形式对于开发高质量软件至关重要。每种技术都有各自的适用场景和局限性,开发者应当根据具体需求灵活运用它们。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值