当试图将数组的元素设置为超类对象时,将出现ArrayStoreException异常


class A {}
class B extends A {}

嗨,我正在学习Java,我试图理解为什么这个工作:

A[] tab = new A[10];
tab[0] = new B();

而不是this:

A[] tab = new B[10];
tab[0] = new A();

这行A[] tab = new B[10];表示编译器在内存中为B预订了10个位置。tab[0] = new A()设置tab[0]等于一个新的A对象,该对象小于B (B extends A)。

为什么有ArrayStoreException: A错误?它是如何工作的?

可以在对象内部存储对象的子类。即B可以存储在A中,但AB类型的超类。基本上,继承链中低于X类的任何类都可以被称为X类型,而继承链中高于X类的任何类都不能被称为X类型。

你的例子

A[] tab = new A[10]; // Perfectly fine. Equal objects.
tab[0] = new B(); // B is a subclass of A, so this is allowed.
A[] tab = new B[10]; // Same principle as above, B is a subclass of A
tab[0] = new A(); // A is a SUPERCLASS of B, so it can not be referred to as A

简而言之,如果XY的子类,则X只能称为Y。(或者子类的子类。这是一个递归定义)。

让我们用一些英语术语

我们用ItemBook代替AB

public class Item {}
public class Book extends Item {}

现在,这样写是有意义的:

Item b = new Book(); // All Books are items.

没有意义:

Book b = new Item(); // All items are definitely not books.

根据文档

抛出,表示试图存储错误的数据将对象类型转换为对象数组。例如代码生成一个ArrayStoreException:

Object x[] = new String[3]; 
x[0] = new Integer(0);

"我的动物数组将只包含蝴蝶(A[] tab = new B[10];)。在数组中添加一个新的动物(tab[0] = new A();)。"

如何确定插入的动物是蝴蝶?

因为如果B扩展A, B拥有A的所有特征(属性,方法等),加上他自己的。

那么每个B也是A,而A(缺乏B的特征)不是B。

这可以归结为层次类型系统最基本的属性,即Liskov替代原则:只要允许a的实例,就允许它的任何子类型的实例。数组没有特殊情况

java的经验法则是超类引用变量可以指向子类对象,反之亦然,如果你仔细想想,父类可以指向子类对象是有道理的。List List = new ArrayList()

给定:

class A { }
class B extends A { }
我们:

A [] a = new A [10]; // can store A or B objects
A [] b = new B [10]; // can only store B objects

最新更新