假设我们不知道有ArrayList这种类而想自行编写维护list的类以保存Dog对象。在之前我们只会写出add()方法。我们使用大小为5的简单Dog数组(Dog[])来保存新加入的Dog对象。当Dog对象超过5个时候,你还是可以调用add()方法,但是什么事情也不会发生。如果没有越界,add()会把Dog装到可用的数组位置中,然后递增可用索引(nextIndex)。
那么,再让你写一个cat,你怎么办?
- 照葫芦画瓢,写一个;
- 创建一个单独的类DogandCatList类,用addCat(Cat c)和addDog(Dog d)来同时处理两个不同的数组实例,这也与不好;
- 编写一个不同的AnimalList类让它处理Animal所有的子类。这应该是最好的办法,所以我们就这样处理,用更通用的Animal来取代个别的子类。
public class AnimalTestDriver {
private Animal[] animal = new Animal[5];
private int nextIndex = 0;
public void add(Animal an) {
if(nextIndex<animal.length) {
animal[nextIndex] = an;
System.out.println("Dog add at"+ nextIndex);
nextIndex++;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
AnimalTestDriver list = new AnimalTestDriver();
list.add(new Dog());
list.add(new Cat());
}
}
其实只是把上面的Dog换个Animal而已。
非Animal呢?为什么不写个万用类呢?
你知道这要怎么做。我们可以修改数组的类型,并且调整add()方法的参数,以处理Animal之上的类。那边是更通用、更抽象的一种类。但是真的有这种类么?我们设计Animal并没有父类啊?
事实上是有的。
还记得ArrayList的方法么?他们是通过对象这个类型来操作所有类型的对象。
在Java中的所有类都是从Object这个类继承出来的。
它是所有类的源头,是所有类的父类。
如果Java中没有共同的父类,那将无法让Java的开发人员创建出可以处理自定义类型的类,也就是说无法写出想ArrayList这样可以处理各种类的类。
就算你不知道,但实际上所有的类都是从对象给继承出来的。你可以把自己写的类想象成是这样声明出来的:
public class Dog extends Object{}
但是Dog本来就是从Canine给extends出来的啊 !
没有关系,编译器会知道改成让Canine去继承对象。事实上是Animal去继承对象。
没有直接继承过其他类的类会是隐含的继承对象
所以就算Dog或者Canine没有直接extends对象,还是会通过Animal来继承对象。
终极对象有什么?
如果你是Java,那你会想要让每个对象都带有什么行为?来个判断相等的方法如何?
我们列出来其中的一部分方法:
equals()
hashCode()
getClass()
toString()
·····
对此,你或许会有这样的疑问:
- Object这个类是抽象类么?
不是。至少不是正式的Java抽象类。因为它可以被所有类继承下来的方法都实现程序代码,所以没有必须被覆盖过的方法。 - 那么是不是可以覆盖过Object的方法?
部分可以。但是有些被标记为final,这代表你不能覆盖掉他们。强烈建议你用自己写的类去覆盖掉equals、toString等待。 - Object类是具体类。怎么会允许人去创建Object的对象呢?这不就是和Animal对象一样不合理么?
因为有的时候你就是会需要一个通用的对象,一个轻量化的对象。它最常见的用途是用在线程的同步化上面(以后再说)。 - 所以Object的主要目的是提供多态的参数与返回类型么?
这个Object类有两个主要的目的:作为多态让方法可以应付多种类型的机制,以及提供Java在执行期对任何对象都有需要的方法的实现程序代码(让所有的类都会继承到)。有一部分是和线程有关。