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
中,但A
是B
类型的超类。基本上,继承链中低于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
简而言之,如果X
是Y
的子类,则X
只能称为Y
。(或者子类的子类。这是一个递归定义)。
让我们用一些英语术语
我们用Item
和Book
代替A
和B
。
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