/*此总结的主要内容是我在学习JAVA过程中,认为需要记忆的知识点。并结合之前自己学习C++及javascript的相关知识,注明JAVA在一些情况下与这两门语言的相同及不同之处。*/
(1)组合
只需将对象引用置于新类中,即意味着组合。
(2)继承
package reusableClass;
//写该示例的原因是有次做笔试题,问到同时存在两个main函数时运行会出现什么样的情况
class Cleanser{
private String s="Cleanser";
public void append (String a){
s+=a;
}
public void dilute(){
append(" dilute()");
}
public void apply(){
append(" apply()");
}
public void scrub(){
append(" scrub()");
}
public String toString(){
return s;
}
public static void main(String[] args){
Cleanser x=new Cleanser();
x.dilute();
x.apply();
x.scrub();
System.out.println(x);
}
}
public class Detergent extends Cleanser{
public void scrub(){
append(" Detergent.scrub()");
super.scrub();//调用基类的方法
}
public void foam(){
append(" foam()");
}
public static void main(String[] args){//测试同一个class文件中存在两个mian方法时的运行情况
Detergent x=new Detergent();
x.dilute();
x.apply();
x.scrub();
x.foam();
System.out.println(x);
System.out.println("Testing base class:");
Cleanser.main(args);
}
//在有两个main函数时,运行时需要选择究竟运行哪个类中的函数,无论选择哪个,都能正常运行。
}
继承的构建过程是从基类向外扩散的,所以基类在导出类构造器可以访问它之前,就已经完成了初始化。
不过这种初始化只会调用不带参数的基类。如果没有默认的基类构造器,或者想调用一个带参数的基类构造器,就必须用关键字super显式的编写调用基类构造器语句,并且配以适当的参数列表。注意,调用基类构造器必须是在导出类构造器中要做的第一件事。
package reusableClass;
//P130
class Game{
Game(int i){
System.out.println("Game constructor");
}
}
class BoardGame extends Game{
BoardGame(int i){
super(i);
System.out.println("BoardGame one constructor");
}
BoardGame(int i,int j){
super(i);
//this(j);//测试用了super调用基类的构造函数后还能否用this调用自身的其它构造函数,结果是不能,
//即在同一个构造函数中,使用了super调用基类的构造函数,就不能再用this调用自身的构造函数
//但是可以考虑在该构造函数中利用this调用其它构造函数,然后用this调用的构造函数调用基类构造函数
//this(i);
System.out.println("BoardGame constructor");
}
}
public class Chess extends BoardGame{
Chess(){
super(11);
System.out.println("Chess constructor");
}
public static void main(String[] args){
//public static void main(String[] args){
Chess x=new Chess();
}
}
PS:在想覆写基类的某个方法时,可以选择添加这个注解,防止不想重载时意外的进行了重载。
(3)代理
这是继承与组合之间的中庸之道。通过实验成员对象的中一部分方法,即能对成员对象有一定的控制力,又能避免暴露成员对象的所有方法。(4)组合与继承之间的选择
(5)protected关键字(补充上一章内容)
(6)向上转型
(7)final关键字
(8)初始化及类的加载
package reusableClass;
//P146
/*程序运行过程
* (1)首先会试图访问main函数
* (2)访问main函数时,会开始加载main函数所在的类Beetle
* (3)如果现在加载的类有基类,会继续加载基类,持续此过程,直到加载到根基类
* (4)从根基类开始沿继承链向上依次初始化类中的static声明
* (5)必要的类被加载完毕后,才会开始运行main函数
* (6)创建不带main函数的其它类过程类同(3)(4),接下来才可以创建类对象,首先,对象中的所有基本类型会被设为默认值。然后,构造器才可以被调用。构造器调用也会沿继承链
* 先不断上溯直到根基类,再依继承链顺序执行构造器的其余部分
*/
class Insect{
private int i=9;
protected int j;
Insect(){
System.out.println("i="+i+",j="+j);
j=39;
}
private static int x1=printInit("static Insect.x1 initialized");
static int printInit(String s){
System.out.println(s);
return 47;
}
}
public class Beetle extends Insect{
private int k=printInit("beetle.k initialized");
public Beetle(){
System.out.println("k="+k);
System.out.println("j="+j);
}
private static int x2=printInit("static Beetle.x2 initialized");
public static void main(String[] args){
System.out.println("main start run");
Beetle b=new Beetle();
}
}
总结中有一段话,是我学习这一章的最大收获。