MarsEdit粘代码好麻烦,全部代码交给github:https://github.com/lozybean/MyJavaLearninghtml
复用一个类经常使用的两种方式:组合、继承;java
将对象引用置于新类中,新类就完成了这些对象的复用;ios
Java中,每一个非基本对象都有一个toString方法,当须要一个String对象时直接调用;对象的引用在类的定义中会被初始化为null;引用初始化能够在四个地方进行:对象定义时 > 实例初始化 > 类构造器中 > 使用对象以前(按初始化顺序排列);示例代码git
使用extends关键字继承一个类的成员(除private以外);github
从示例代码中,能够看到main方法能够存在于多个类中,这样的写法为了单元测试更加简便易行(翘首以待),即使Cleanser并非public类,可是public main()仍然能够被外部调用;即:即便一个类只具备包访问权限,其public main()仍然是可访问的;编程
Detergent类使用extends继承了Cleanser,即实现了Cleanser中全部可继承方法的复用;不只如此,还能够在Detergent类中对某些方法进行改写,如scrub()方法,在改写过程当中,若是须要调用基类的同名方法,则使用super.scrub()来调用;固然,Detergent类能够定义除了继承来的方法以外的方法;swift
在子类建立对象以前,会先进行基类的初始化;也就是说,当建立了一个子类的对象时,不只仅复制了基类的接口,会包含一个基类的子对象,该子对象包装在子类的对象内部,并具备直接使用基类建立的对象同样的属性;如:示例代码中,在Cartoon类构造器能够访问到对象以前,基类的构造器就能够访问到,而且完成初始化;即便没有Cartoon构造器,编译器也会产生一个默认的构造器,而且调用基类的构造器;而且能够看到,当C类继承A类,而且有一个B类的对象时,若是实例化C类对象,则会先调用A类的构造器,再调用B类构造器,最后调用自身构造器(若是没有定义的话,则不会调用);编程语言
当基类中的构造器不是默认构造器,而是带参数的构造器,而且没有默认构造器时,则必须在子类中使用super(args)调用该构造器,并传入相应的参数列表,不然没法完成基类的构造,编译器报错;示例代码ide
子类中的构造器执行顺序为:包含其余类对象的构造器(当该对象是直接初始化时,若是在构造器中初始化,则和子类构造器一个顺序级别)、基类构造器、子类构造器;若前二者没有默认的构造器,则包含其余类对象必须正确调用构造器,基类必须使用super(args)正确调用构造器;示例代码函数
继承过程的初始化过程为:1. 加载基类、基类的static初始化;2. 若是加载基类的过程当中,发现还有基类,则先加载该基类,执行static初始化,而后再回到第一个基类中的static初始化过程,依次类推;3. 基类加载完成后建立对象,调用基类构造器(生成隐含子对象),而后再调用子类构造器,完成对象建立;如示例代码中,执行Beetle.main()时,先加载Beetle类,发现有一个基类Insect,并加载该基类,以及其static成员的初始化,而后完成Beetle类的static初始化,接着才是顺序执行println语句,以后新建一个Beetle对象,先进行基类的数据成员加载,而后调用基类的构造函数,接着进行子类的数据成员加载,最后调用子类的构造函数;只有这样的过程,才能保证子类所依赖的基类成员被正确初始化;
java并无提供代理的直接支持,将一个成员对象置于所要构造的类中,但同时又在新类中暴露该成员对象的全部方法;即在新类中添加一个想要继承类的对象,而后在新类中实现该对象的方法,此时,使用该代理建立的对象即可经过实现的方法拥有和继承类相同的接口;不一样的是,代理能够选择继承方法中的某个子集,因此具备更加灵活的控制力;示例代码
java中,析构函数能够在对象被销毁时自动调用(finalize()方法),当须要在一个类的生命周期内执行一些必须的清理活动,除了finalize()方法外,并不能知道java在什么时候销毁一个对象,可是将该方法置于finally子句中,能够保证该方法被调用(不管是正常执行仍是异常退出);即:
try{
// … do something
} finally{
x.dispose(); //这里是本身实现的清理方法,该方法必定会被执行;
}
在实现清理方法时,必须注意基类和成员对象清理方法的调用顺序,防止某个子对象依赖于某个子对象的情形发生;(通常来讲,按照构造器调用的相反顺序),如:示例代码
在java中重载某个基类的方法时,并不须要(如C++中)将该方法屏蔽,而可使用基类中的全部重载方法;如:示例代码中,Bart重载了方法doh,并使用了新的参数列表,可是Bart类实例化的对象仍然能够调用Homer中的同名方法;
这样的特性有时会引发迷惑,因此Java SE5新增长了@Override注释(并非关键字),当给某个方法添加该注释后,若是子类直接调用该方法则会产生错误,必须重载该方法才能正确使用;(忽然明白swift ios开发学习时用到的各类override)
组合和继承虽然均可以复用对象,组合是显式地将子对象放到新类中,而继承是隐式地将子对象放到新类中;
组合经常使用于想在新类中实现现有类的功能,而非它的接口这种情形,即,在新类中嵌入某个对象,让该对象来实现须要的功能,因为新类的用户想要看到的是新类的接口,而非嵌入对象的接口,因此须要用private来嵌入该对象;但有时,容许新类中的组合成分可见是颇有意义的,此时应该使用public来嵌入该对象;
继承经常使用于要使用某个现有的类,并开发它的一个特殊版本;继承能够得到基类中的protected域,这是组合和代理所没法完成的;继承更加剧要的方面是表现:新类是现有类的一种类型(书上翻译的名词,感受容易混肴,这里的类型不是编程语言中的术语,而是天然语言中的类型),经过继承能够实现向上转型,即在导论中提到的例子,一个基类的方法能够直接处理子类,这样作的好处是将方法通用化,实现特殊化;若是设计上没有明确要求向上转型的操做,则应该慎重考虑使用继承,而经常使用组合;
而代理则是使用组合实现子对象的功能时,添加相应的接口方法,是对基类的某部分进行从新实现;
final关键字指没法改变的;
当final用于数据时,表示该数据是一个常量,或者在运行时被初始化的值,可是不但愿被改变;习惯上,将既是static又是final的域用大写表示,并使用下划线来分割每一个单词;java容许生成空白final,即在指定final时并未直接初始化,可是空白final必须确保在使用前初始化;
当final用于参数时,表示在方法中没法更改该参数引用的对象;
当final用于方法时,表示该方法别锁定,不能在继承中重载;类中全部的private方法都隐式地被添加final关键词;
当final用于类时,表示该类不可被继承;