您的位置:首页 > 编程语言 > Java开发

JAVA自学笔记(二):重用与多态

2009-07-28 22:29 239 查看
这部分内容对应Thinking in JAVA 3rd P202-P264,我手上的是EBOOK不得不说这部分的翻译是比较烂的,不知道纸质版会不会好一点。特别指出一点,书上的一些称为重载的地方应该是重写,重载这个术语的意义并不是这本书上所写的,具体可以参考任何一本C/C++的书。

这部分其实较C++而言并没有太多不同的东西,一些不同的东西大多书还是存在在一些关键字上面。

一、名字屏蔽和重载

C++程序员对一个事实应该很清楚,假设在基类当中有这样一组重载函数:

//C++ code

class base

{

public:

int f(int);

int f(double);

int f(char);

};

一旦你写了这样的一个继承类:

//C++ code

class devered : public base

{

public:

int f(int);

};

那么在继承类当中可以使用的称为f的成员函数只有f(int)一个,而基类当中的其他名为f的函数全部不可见,这在C++当中称之为名字屏蔽。

在JAVA当中不存在这种名字屏蔽,如果在继承类当中声明了一个与基类同名的方法,那么他将与基类当中所有同名方法构成一个重载函数组,对继承类而言,这组函数将按照重载规则进行选择。当然,如果继承类当中声明的一个函数声明的签名与基类完全相同,那么这个函数(仅此一个,不包括重载函数组当中的其他函数)将被重写,后面可以看到,对JAVA而言重写和覆盖完全是一回事情,因为JAVA只有后绑定。

二、后绑定

后绑定是OOP的一个重要特征,他的行为就是根据实际引用的对象类型来决定调用哪个方法。对C++而言,因为类对象可以直接表示(存在在堆栈上)也可以间接表示(用指针或者引用),对于直接表示的对象,因为后绑定的基础是向上转换,而直接表示的对象一旦向上转换就直接在内存中被截取为基类对象,因此这里表现的是一种覆盖的行为,而用间接表示的对象则是后绑定的行为。而JAVA的类对象只能以引用来表示,因此,他表现出来的行为都会是后绑定。正因为如此,JAVA当中的方法不需要像C++当中一样用一个关键字(C++当中的virtual)来明确表示这个方法是后绑定方法。

三、final关键字

final关键字可以认为是C++当中const关键字的等价物(至少引用在对象和基础类型上是如此)。对于基础类型对象,final表明这个成员一旦被初始化以后将不能被改变,而对与类对象而言,因为类对象在JAVA当中是引用,所以表示的是指向的类对象一旦被初始化设定以后不能再指向其他的类对象(类似与CPP当中的const 引用或者const指针)。区别与CPP在JAVA当中这里有个相对宽松的设定,JAVA当中如果你不去初始化成员,那么这些成员将被默认初始化为0或其等价值,但是对于final成员而言,所谓的初始化后不能改变指的是程序员的初始化而不是默认初始化,也就是说你可以不去初始化这些成员,直到需要的时候再去初始化,当然这种初始化只允许你做一次。

final方法。方法也能被final关键字修饰,这里的final就跟CPP当中的const不等价了,这里的final指的是这个方法可以被继承类继承但是不允许继承类去重写这个方法。基于private方法对继承类而言不可见,因此JAVA基于性能的考量直接把private方法隐式地写成了final。顺便提一句在继承结构当中public、protected、private方法和成员的存在方式直接用CPP规则理解就好,这本书上写的个人感觉很乱。

四、完整的类初始化过程

在第二部分的笔记当中提到过类的初始化过程,当时总结的时候排除了继承结构。这里将要总结包括继承结构的完整类初始化过程。

a.计算类对象的大小,获得内存区域后将内存全部初始化为0(这直接导致所有成员的值为0);

b.对于单个类,类初始化过程首先按照成员声明顺序初始化各个成员(声明时有初始化语句的初始化,否则不动保持0),然后调用指定的构造函数;

c.对于继承结构当中的类对象,首先构造其直接基类,如果存在继承链,那么可以看到这个过程将会是递归的,最终结果就是根据继承链从最基础的类对象开始构造,每个基类的构造过程遵照b的描述进行,当基类全部构造完毕后开始构造继承类,继承类的构造也遵照b的描述进行。

五、清除过程

原则上由于垃圾回收机制的存在JAVA不需要CPP当中的析构函数,但是如果存在一些独占资源,因为垃圾回收机制并不能保证不被使用的对象立刻被回收,因此这个清除的过程需要程序员来干预,也就是说程序员需要写一个与CPP类似的析构函数,然后调用。资源释放的方式与CPP的析构函数完全一样:按声明顺序的反方向依次清楚继承类的资源然后调用基类的清除过程。

六、表示基类的super关键字

在JAVA当中统一super用来表示基类。你可以用super来调用基类的方法,也可以在继承类构造函数的第一行用super来调用基类的构造函数。顺便提一句,用super调用基类构造函数必须在继承类构造函数体的第一行(可以没有,那么隐式地调用基类的默认构造函数)。由于JAVA不存在CPP当中的初始化列表,而两者的初始化机制其实是一样的,所以你可以得到这样的一个结论,CPP在初始化列表当中调用基类构造函数必须是第一个表项,因此,即便JAVA调用基类构造函数在继承类构造函数体内,实际的情况是基类首先被初始化然后再是继承类成员声明上的初始化最后才是继承类的初始化函数体。

七、虚类和虚方法

JAVA当中虚类和虚方法的定义和CPP一致,不同的是JAVA当中的关键字是abstract,而且不需要CPP当中的=0写法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: