我在Java中遇到过一些我无法理解的代码。它在java中使用多态。
public class MyAnimalList {
private Animal[] animals = new Animal[5];
private int nextIndex = 0;
public void add(Animal a) {
if (nextIndex < animals.length) {
animals[nextIndex] = a;
System.out.println("Animal added at " + nextIndex);
nextIndex++;
}
}
}
public class AnimalTestDrive{
public static void main (String[] args) {
MyAnimalList list = new MyAnimalList();
Dog a = new Dog();
Cat c = new Cat();
list.add(a);
list.add(c);
}
}
这里引用堆上的dog对象的引用变量a
正被传递给add
函数。现在,当引用作为参数时,作为Animal a
参数接收。我的问题从这里开始,animals[0]=a
,即animals[0]
指的是由a引用的对象。
animals[1]=a
这意味着它也指向a引用的对象,即同一个对象。
如果所有动物数组引用都指向同一个对象,那么新的dog-list是如何创建的?
答案 0 :(得分:2)
Dog a = new Dog();
此处,a
是对Dog
对象的引用。
此引用将传递给add(Object a)
方法。
此处,a
是Dog
引用变量,会被转换为Animal
引用变量。但仍然指向相同的Dog
对象。虽然现在是动物参考变量。然后传递并添加到列表中。
不要与Dog a
和add(Animal a)
混淆。这两个a
引用完全不同。 Dog a
,是传入方法时转换为Animal a
。这两个不是一回事。您可以根据需要为其命名。
这是可能的,因为class Dog extends Animal
。
现在,假设有3个狗对象
Dog a = new Dog();
Dog b = new Dog();
Dog c = new Dog();
假设在Dog
类中,有一个实例变量String name;
因此,对于每个Dog
对象,您可以设置不同的名称。
a.setName("Tom");
b.setName("Dick");
c.setName("Harry");
现在您可以通过
将这些添加到列表中list.add(a);
list.add(b);
list.add(c);
所有对象引用都被强制转换为Animal
引用并添加到同一列表中。但它们都涉及不同的对象。在数组中使用不同的名称。
现在,类似地,Cat
类也扩展了Animal
。因此,您可以制作Cat
个对象并将它们转换为Animal
个对象,然后将它们添加到列表中。
因此,我们只能放置{{1},而不只是拥有Dog
个对象,Dog[]
或Cat
个对象Cat[]
的数组。对象或Dog
对象,我们可以利用多态,并创建一个supercalss Cat
的数组,并将子类对象全部转换为Animal
超类对象,然后将它们全部放在一起。 Animal
和Cat
个对象一起保留在列表中。
答案 1 :(得分:1)
有两个不相关的东西名为a
。在一个类的main方法中有一个局部变量,在另一个类上有一个add方法的参数。方法中声明的局部变量在该方法之外是不可见的,因此add方法无法看到main方法中声明的a
。
main中用于调用add方法的代码为每个调用提供不同的对象,因此引用不指向同一个对象; add方法的参数指向传入的内容。在第一次调用add时,参数a
引用main方法中局部变量a
引用的Dog。在第二次添加调用中,参数a
引用局部变量c
引用的Cat。
答案 2 :(得分:0)
你可能会对你的主要代码中的胖子感到困惑,你有Dog变量&#39; a&#39;并在你的添加&#39;方法也有一个同名的变量。
但我希望我能以最好的方式回答你的问题。
当你说
时list.add(a)的
实际发生的是,当您调用该方法时,您将获得一个引用旧方法的新Object(这意味着您对方法中对象所做的所有更改将保留在原始对象中)并且您可以想到它就像你原始变量名称的改变 - 莫名其妙。
这意味着当你说
时list.add(C); 你在add方法中拥有的是变量a中的Animal类型Cat。