Java ArrayList中是否存在子类对象<;超类>;保持方法对子类是唯一的?

Java ArrayList中是否存在子类对象<;超类>;保持方法对子类是唯一的?,java,inheritance,arraylist,Java,Inheritance,Arraylist,基本上是标题所说的,但有些细节。我有一个超类和几个子类。我需要一个ArrayList来保存这两种类型的子类,因此类型为超类的ArrayList。我尝试使用ArrayList.get(0.getQuantity())访问子类1的getQuantity()方法(假设索引0的类型为子类1)。我得到一个错误:类型超类的getQuantity未定义 子类对象在放入超类ArrayList时是否不保留其属性?如果它们确实保留了它们的属性,我如何访问它们呢?对象本身仍然是一个子类,但是当您将它们从集合中取出时,

基本上是标题所说的,但有些细节。我有一个超类和几个子类。我需要一个ArrayList来保存这两种类型的子类,因此类型为超类的ArrayList。我尝试使用
ArrayList.get(0.getQuantity())访问子类1的
getQuantity()
方法(假设索引0的类型为子类1)。我得到一个错误:类型超类的getQuantity未定义


子类对象在放入超类ArrayList时是否不保留其属性?如果它们确实保留了它们的属性,我如何访问它们呢?

对象本身仍然是一个
子类
,但是当您将它们从集合中取出时,它只知道
超类
,所以它不能告诉您哪个是哪个,它必须选择公共分母

如果您确切知道某个特定索引包含类型为
Subclass
的对象,则可以强制转换它:

Subclass myObject = (Subclass) list.get(0);
System.out.println(myObject.getQuantity());
它应该会起作用

更安全的方法是测试对象是否真的是您认为的对象:

SuperClass myObject = list.get(0);
if ( myObject instanceof Subclass) {
  Subclass mySubObject = (Subclass) myObject;
  System.out.println(mySubObject.getQuantity());
}
如果对象不是
子类类型
,则第一个示例会引发异常,第二个示例不会引发异常,因为它之前进行过测试以确保

这里需要了解的是
超类myObject=list.get(0)
不是对象本身,而是访问内存中对象的引用。把它想象成一个可以让你控制你的对象的遥控器,在这种情况下,它不是一个功能齐全的遥控器,因为它不能向你展示你的对象所能做的一切,所以你可以切换到一个更好的遥控器(如
Subclass myObject=(Subclass)list.get(0)
)来访问所有功能


我当然会推荐,因为它非常详细地介绍了这些内容(我从那里偷了这个远程示例)。

所有对象都保留自己的类标识,但是使用
ArrayList的代码并不直接知道它。就它而言,
ArrayList
只保存对
超类
类型对象的引用,并且它只能对从中检索的对象调用
超类
的方法


调用代码可以使用
instanceof
或类似技术来确定集合中的特定对象是否属于子类型,但这通常是不好的做法,因为它通常表示不同抽象级别的混合。通常认为这是合理的一种情况是,如果子类具有调用方可以利用的一些可选的高性能特性(并且该度量已确定值得使代码复杂化);一个例子可能是,虽然
List
get()
方法没有性能保证,但一些实现,如
ArrayList
,也实现了
RandomAccess
,这表明使用
get()没有性能损失
以任何顺序。

当您有一些ArrayList,并用扩展超类的内容填充它时,您必须检查instanceof和cast以获得特定于这些子类的方法

例如:

ArrayList<Animal> animals = new ArrayList<Animal>;
animals.add(new Duck());
animals.add(new Cow());
animals.add(new Horse());

for (Animal animal : animals) 
   if (animal instanceof Horse) {
      Horse horse = (Horse)animal;
      horse.gallop();
   }
ArrayList animals=新的ArrayList;
添加(新鸭子());
动物。添加(新奶牛());
动物。添加(新马());
用于(动物:动物)
if(马的动物实例){
马=(马)动物;
马。奔驰();
}

起初,这听起来像是重复的,但经过大约20分钟的研究,一些帖子触及了相同的主题,但没有完全回答我的问题。回答得好。我想知道甲骨文将来是会解决这个问题,还是干脆不处理它。见鬼,这可能是某种用途,但我想不出任何用途。这不是问题,这就是面向对象语言(和泛型)的工作原理,你不能说你的列表只包含
子类,因为它不包含子类,编译器必须强制执行。我将在本学期后购买Head-First设计模式:),我的意思是,我想知道他们是否会添加一些自动切换“遥控器”的东西,而不必说我正在切换“遥控器”。我认为这可能是有用的。他们可能会在语言中构建一个模式匹配器来帮助实现这一点,这样可以避免序列的丑陋的
实例,但这通常是设计糟糕的标志(正如@chrylis其他解决方案所指出的)你应该尽可能避免这种风格。但我看到的是,除非你重新构造它,使ArrayList不包含两种类型的子类,否则没有其他办法了?@comscis是的,但这通常是正确的做法。如果您关心
子类1
子类2
之间的差异,通常不应该将它们放在一个集合中,而应该将它们放在不同的集合中。了解这些信息很好。出于我的目的,尽管我需要它们在同一个ArrayList中。一个子类是费用,另一个子类是收入。我想按添加顺序跟踪它们。将它们分开会增加很多复杂性,因此,这次我将抄近路;)但是我知道哪里会有麻烦。@COMSCI根据您特别希望调用
收入
费用
的方法,正确的方法可能是在
条目
上添加一个
抽象
方法,具有
列表的代码可以调用该方法。这样它就知道它可以调用“任何子类的正确事物”,而不必知道某个特定对象是哪个子类。这是一个有趣的想法。我将在下一个项目中牢记这一点!