JavaFX中如何创建已有Shape的新实例(副本)?
解决方案:创建独立的Shape实例
这个问题我太熟悉了——Java里直接赋值对象变量本质上只是复制引用,不是真的创建新对象,所以你才会遇到修改box就影响原shape的情况。要创建属性完全相同的独立实例,你有这几种靠谱的解决方案:
1. 给Shape类添加拷贝构造函数
这是最直观也最可控的方式。你可以在Shape类里定义一个接收同类型实例的构造函数,把原对象的所有属性逐个复制到新对象里。
比如假设你的Shape类有这些核心属性:
public class Shape { private int width; private int height; private Color color; // 引用类型属性,注意深拷贝 // 普通构造函数 public Shape(int width, int height, Color color) { this.width = width; this.height = height; this.color = color; } // 拷贝构造函数 public Shape(Shape original) { this.width = original.width; this.height = original.height; // 注意:如果是引用类型属性,要创建新实例避免共享引用 this.color = new Color(original.color.getRGB()); } }
然后在你的Box构造里,就可以用这个拷贝构造函数创建独立实例:
public class Box extends CenaVisivel { public Shape box = null; public Box(Shape shape){ box = new Shape(shape); // 这里创建了全新的Shape对象 // ... 其他逻辑 } }
2. 实现Cloneable接口并重写clone方法
Java提供了原生的克隆机制,不过需要注意浅拷贝和深拷贝的区别:
首先让Shape实现Cloneable接口,然后重写clone()方法:
public class Shape implements Cloneable { private int width; private int height; private Color color; // ... 构造函数和其他方法 @Override protected Object clone() throws CloneNotSupportedException { // 先做浅拷贝 Shape cloned = (Shape) super.clone(); // 对引用类型属性做深拷贝,避免共享对象 cloned.color = new Color(this.color.getRGB()); return cloned; } }
然后在Box构造里调用clone方法(注意处理异常):
public Box(Shape shape){ try { box = (Shape) shape.clone(); } catch (CloneNotSupportedException e) { // 这里可以根据业务逻辑处理异常,比如抛出运行时异常或者创建默认实例 throw new RuntimeException("无法克隆Shape实例", e); } // ... 其他逻辑 }
3. 如果无法修改Shape类(比如是第三方库的类)
如果Shape是你没法修改的第三方类,那只能手动创建新实例,逐个复制所有可访问的属性:
public Box(Shape shape){ box = new Shape(); // 假设Shape有无参构造 // 逐个复制属性,根据Shape提供的getter/setter方法 box.setWidth(shape.getWidth()); box.setHeight(shape.getHeight()); box.setColor(new Color(shape.getColor().getRGB())); // ... 复制其他所有属性 }
关键注意点
如果Shape里包含引用类型的属性(比如自定义的Point对象、集合等),一定要做深拷贝——也就是为这些属性也创建新的实例,而不是直接复制引用。否则这些属性还是会和原对象共享,修改时依然会互相影响。
内容的提问来源于stack exchange,提问作者Guilherme Da Bolsa
相关产品推荐
相关产品推荐

