Java创建新对象

3
我有一个抽象类Specie,然后是继承自species的Animals类,再然后是我的动物类(例如Sheep)。在Animals中,我有一个方法来检查两个对象是否在地图上处于相同的位置,并且它们是相同类型的(例如Sheep和Sheep)。
如果是,则会创建另一只Sheep。但我有问题。 我尝试了类似以下的代码:
Specie new_specie = this;

在我的Sheep类中有一个复制构造函数

     public Sheep(Sheep new_sheep){

     this(new_sheep.get_x(),new_sheep.get_y(), new_sheep.get_img());
}

然后将其保存到包含所有对象的数组中。

species[speciesAmount] = new_specie;

但它只是将同一对象保存在数组的两个元素中。
species[0]
species[2]

同一个对象。有任何想法吗?

但是还有另外一个问题,我会有更多种类的动物(例如狼),我无法处理。

new Specie(this)

因为它是一个抽象类。

如何使它调用正确的构造函数?

编辑。我解决了,我使用了clone()方法。


2
公共的Sheep(Sheep new_sheep){ 你看到这个问题了吗?基本上,你需要有一个Sheep实例,才能创建一个... - Stultuske
但是还有另一个问题,我会有更多类型的动物(例如狼),而且我不能执行new Specie(this)因为它是一个抽象类,如何使其调用适当的构造函数? - Cardano
1
新的 Specie(this) 在我看来有点荒谬,如果你需要类似的东西,只需使用 clone 方法就可以了。 - Stultuske
我听说不应该使用它,因为它已经过时了或者类似的原因。但是我会尝试一下,谢谢。 - Cardano
我写了一个答案,应该可以帮助你进行克隆。然而,你应该学习更多关于Java的知识,因为你正在将C++的习惯带到Java编程中(包括命名规范),当然,这也有其不足之处。 - Vlasec
另外,你可能会感兴趣的是,使用克隆仅对可变对象有用。如果你有一个不可变的对象,克隆只会浪费资源。 - Vlasec
3个回答

3

Specie new_specie = this;会创建一个名为new_specie的新引用,并让它引用与this相同的对象。因此,species [speciesAmount] = new_specie;将把相同的引用分配给数组条目(它本身是一个引用)。

您的代码根本没有调用复制构造函数。与C ++不同,在Java中调用复制构造函数必须像这样:

Specie new_specie = new Sheep(this);

顺便提一下,您可能需要查看Clonable接口,该接口旨在提供对象复制功能。
更新:关于您的第二个问题,解决方案取决于您想要实现什么。如果您只想要一个具体物种的副本,当有两个物种时就在一个字段上,您可以比较这两个物种的类(使用getClass()方法)或使用equals()检查相等性(取决于您如何定义,通常不仅是相等类)。
然后,您基本上只需调用Species new_species = species_on_field.clone()并获得该字段之前的克隆即可。
另一个选择可能是基于该字段上当前物种的类使用工厂模式或原型。我将让您自己在网络上查找。

2

在Java中,你不能使用赋值符号调用复制构造函数,你必须显式地调用它!

species[0] = new Sheep(this);

1
你可以通过比较它们的类别来比较物种,例如:
if (specieA.getClass() == specieB.getClass) {

接下来,您的下一步是创建一个新物种。在运行时,可以使用反射访问此信息。这并不是什么美好的事情,但有时是不可避免的(例如,您不想为每个物种创建一个switch-case):

    Class<?> clazz = specieA.getClass();
    Specie newSpecie = clazz.getConstructor(clazz).newInstance(specieA);
}

这个代码会寻找specieA类的构造函数(在此处命名为clazz),它接受一个clazz实例作为输入参数。这样,你应该能够克隆任何东西(当然前提是它有一个复制构造函数)。如果没有这样的构造函数,就会抛出异常(你需要用try-catch来处理)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接