think in java回顾整理之类再生


面向对象的三个特性:封装、继承、多态。

类再生
第一种:在新类里简单地创建原有类的对象。我们把这种方法叫作“合成”,因为新类由现有类的对象合并而成。
第二种:创建一个新类,将其作为现有类的一个“类型”。我们可以原样采取现有类的形式,并在其中加入新代码,同时不会对现有的类产生影响。这种魔术般的行为叫作“继承”(Inheritance),涉及的大多数工作都是由编译器完成的。

代码再生或者重复使用的机制。

为进行合成,我们只需在新类里简单地置入对象句柄即可。

希望句柄得到初始化,可在下面这些地方进行:
(1) 在对象定义的时候。这意味着它们在构建器调用之前肯定能得到初始化。
(2) 在那个类的构建器中。
(3) 紧靠在要求实际使用那个对象之前。这样做可减少不必要的开销——假如对象并不需要创建的话。

创建一个类时肯定会进行继承,因为若非如此,会从Java的标准根类Object中继承。


Java提供了一个super关键字,它引用当前类已从中继承的一个“超类”(Superclass)。

基础类及衍生类:
基础类子对象应该正确地初始化,而且只有一种方法能保证这一点:在构建器中执行初始化,通过调用基础类构建器,后者有足够的能力和权限来执行对基础类的初始化。在衍生类的构建器中,Java会自动插入对基础类构建器的调用。

基础类会在衍生类访问它之前得到正确的初始化。

编译器会强迫我们在衍生类构建器的主体中首先设置对基础类构建器的调用。

如果Java基础类有一个方法名被“过载”使用多次,在衍生类里对那个方法名的重新定义就不会隐藏任何基础类的版本。所以无论方法在这一级还是在一个基础类中定义,过载都会生效。


如果想利用新类内部一个现有类的特性,而不想使用它的接口,通常应选择合成。也就是说,我们可嵌入一个对象,使自己能用它实现新类的特性。
如选择继承,就需要取得一个现成的类,并制作它的一个特殊版本。通常,这意味着我们准备使用一个常规用途的类,并根据特定的需求对其进行定制。
“属于”关系是用继承来表达的,而“包含”关系是用合成来表达的。


继承是对新类和基础类之间的关系的一种表达。可这样总结该关系:“新类属于现有类的一种类型”。这种表达并不仅仅是对继承的一种形象化解释,继承是直接由语言提供支持的。


由于造型的方向是从衍生类到基础类,箭头朝上,所以通常把它叫作“上溯造型”,即Upcasting。
上溯造型肯定是安全的,因为我们是从一个更特殊的类型到一个更常规的类型。换言之,衍生类是基础类的一个超集。它可以包含比基础类更多的方法,但它至少包含了基础类的方法。

为判断自己到底应该选用合成还是继承,一个最简单的办法就是考虑是否需要从新类上溯造型回基础类。
若必须上溯,就需要继承。但如果不需要上溯造型,就应提醒自己防止继承的滥用。


final关键字的三种应用场合:数据、方法以及类。

数据final:
public表示它们可在包外使用;Static强调它们只有一个;而final表明它是一个常数。

final值设为static和非static之间的差异。只有当值在运行期间初始化的前提下,这种差异才会揭示出来。因为编译期间的值被编译器认为是相同的。

将句柄变成final看起来似乎不如将基本数据类型变成final那么有用。

对于基本数据类型,final会将值变成一个常数;但对于对象句柄,final会将句柄变成一个常数。

空白final都必须在实际使用前得到正确的初始化。而且编译器会主动保证这一规定得以贯彻。然而,对于final关键字的各种应用,空白final具有最大的灵活性。

方法final:
第一个是为方法“上锁”,防止任何继承类改变它的本来含义。
第二个理由是程序执行的效率。将一个方法设成final后,编译器就可以把对那个方法的所有调用都置入“嵌入”调用里。

只有在方法的代码量非常少,或者想明确禁止方法被覆盖的时候,才应考虑将一个方法设为final。

类内所有private方法都自动成为final。

类final:
整个类都是final(在它的定义前冠以final关键字),就表明自己不希望从这个类继承,或者不允许其他任何人采取这种操作。类肯定不需要进行任何改变;或者出于安全方面的理由,我们不希望进行子类化(子类处理)。

一个final类中的所有方法都默认为final。


static首次使用的地方也是static初始化发生的地方。
装载的时候,所有static对象和static代码块都会按照本来的顺序初始化(亦即它们在类定义代码里写入的顺序)。当然,static数据只会初始化一次。


若基础类含有另一个基础类,则另一个基础类随即也会载入,以此类推。接下来,会在根基础类(此时是Insect)执行static初始化,再在下一个衍生类执行,以此类推。保证这个顺序是非常关键的,因为衍生类的初始化可能要依赖于对基础类成员的正确初始化。

必要的类已全部装载完毕,所以能够创建对象。首先,这个对象中的所有基本数据类型都会设成它们的默认值,而将对象句柄设为null。随后会调用基础类构建器。在这种情况下,调用是自动进行的。但也完全可以用super来自行指定构建器调用(就象在Beetle()构建器中的第一个操作一样)。基础类的构建采用与衍生类构建器完全相同的处理过程。基础顺构建器完成以后,实例变量会按本来的顺序得以初始化。最后,执行构建器剩余的主体部分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值