复用类
通过组合或继承
7.1组合语法
只需将对象引用置于新类中即可;
初始化类成员引用的方式:
1、在定义对象的地方。
2、在类的构造器中。
3、在正要使用这些对象之前,这种方式称为惰性初始化。
4、实例初始化
示例:
public class Demo{
String s1="Happy";
String s2,s3,s4;
public Demo(){s2="Happy";}
{s4="Happy";}
public String toString(){
if(s3==null){s3="Happy";}
return "s1= " + s1 + "\n" + "s2= " + s2 + "\n" + "s3= " + s3 + "\n" + "s4= " + s4 + "\n";
}
}
7.2继承语法
使用extends关键字;
为了继承,一般的规则是将所有数据成员都指定为private,将所有的方法指定为public(protected略);
Java用super关键字表示超类的意思;
继承复制了基类的接口;
Java会自动在导出类的构造器中插入对基类构造器的调用;(构建过程是从基类“向外”扩展的,所以基类在导出类构造器可以访问它之前,就已经完成了初始化);如果没有默认的基类构造器,或者想调用一个带参的基类构造器,就必须用super语句;
7.3代理
继承与组合的中庸之道:我们将一个成员对象置于所要构造的类中,与此同时我们在新类中暴露了该成员对象的所有方法。
7.4结合使用组合和继承
如果Java的基类拥有某个已经多次重载的方法名称,那么在导出类中重新定义该方法名称并不会屏蔽其在基类中的任何版本。因此无论是在该层或者它的基类中对方法进行定义,重载机制都可以正常工作。
7.5在组合与继承之间选择
组合技术通常用于想在新类中使用现有类的功能而非它的接口这种情形。即,在新类中嵌入某个对象,让其实现所需的功能,但新类的用户看到的只是为新类所定义的接口,而非所嵌入对象的接口;
继承用于,使用某个现有类,并开发一个它的特殊版本。通常,这意味着你在使用一个通用类,并为了某种特殊需要而将其特殊化。
is-a VS has-a
7.6protected关键字
将某些事物尽可能对这个世界隐藏起来,但仍然允许导出类的成员访问它们。
protected也提供了包访问权限;
7.7向上转型
“为新的类提供方法”并不是继承技术中最重要的方面,其最重要的方面是用来表现新类和基类之间的关系。这种关系可以用“新类是现有类的一种类型”这句话加以概括。
在方法参数为基类引用时,程序代码可以对基类和它的所有导出类起作用,这种将导出类引用转换为基类引用的动作,我们称之为向上转型。
对于组合与继承,到底是该用组合还是用继承,一个最清晰的判断方法就是问一问自己是否需要从新类向基类进行向上转型。如果必须向上转型,则继承是必要的,否则,应当好好考虑自己是否需要继承。
7.8final关键字
final数据:数据恒定不变。对于基本类型,final使数值恒定不变,对于对象引用,final使引用恒定不变。一旦引用被初始化指向一个对象,就无法把它改为指向另一个对象。然而,对象其自身却是可以修改的。
空白final:声明为final但又未给定初值的域;编译器在任何情况下都确保空白final在使用前必须初始化。必须在域的定义处或者每个构造器中用表达式对final进行赋值。
final参数:Java允许在参数列表中以声明的方式将参数指明为final。这意味着你无法在方法中更改参数引用所指向的对象。
final方法:把方法锁定,防止任何继承类修改它的含义。这是出于设计的考虑:想要确保在继承中使方法行为保持不变,并且不会被覆盖。
final类:不能继承该类,也不允许别人这样做。
有关final的忠告:将一个方法指定为final,可能会妨碍其它程序员在项目中通过继承来复用你的类,而这只是因为你没有想到它会以那种方式被运用。
7.9初始化及类的加载
示例:编译器加载类A、注意到它有一个基类B,于是继续进行加载。接下来,基类的static初始化即会被执行,然后是导出类的static初始化。(因为导出类的static初始化会依赖于基类成员能否被正确初始化)。至此类加载完毕,对象就可以创建了,首先对象中的基本类型都会设置为默认值,对象引用设置为null,然后基类的构造器会被调用。
附:
父类静态域——>子类静态域——>父类成员初始化——>父类构造块——>父类构造方法——>子类成员初始化——>子类构造块——>子类构造方法