继承是面向对象的最显著的一个特征。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
1.super、this 关键字
super,代表父类的存储空间标识。(可以理解为父亲的引用,但不是引用)。
this,代表对象的引用(谁调用就代表谁)。
1.1 成员变量
this.变量 ---- 本类的
super.变量 ---- 父类的
1.2 成员方法
this.方法名 ---- 本类的
super.方法名 ---- 父类的
1.3 构造方法
this(…) ---- 本类的构造方法(可以实现在本类中调用构造方法)
super(…) ---- 父类的
都必须在构造方法的第一行。
class Car { private String name; Car(String name) { this(); //--在本类中调用自己的构造方法 this.name = name; } private Car() { System.out.println("Car name:" + this.name); } } public class TestClass { public static void main(String[] args) { Car car = new Car("Volvo"); } }output: Car name:null
2.初始化顺序:
http://www.cnblogs.com/maying3010/p/5866128.html
3.构造函数、方法调用
3.1 当子类继承父类时,需要调用父类的构造函数。主要三种情况:
(1). 父类没有构造函数或者有一个无参构造函数时,子类可以不用显示的调用父类的构造函数,系统会自动的调用。
(2). 父类只有有参构造函数,则必须在子类的构造函数中调用父类的构造函数(使用super关键字)。
(3). 父类既有无参构造函数又有有参构造函数,子类则可调用可不调用。
3.2 方法调用 :
(1). 使用super关键字调用父类的方法。
class Car { private String str; Car(String str) { this.str = str; System.out.println("This is Car"); } @Override public String toString() { return str; } } class Volvo extends Car { Volvo(String str) { super(str); //--调用父类的构造函数 System.out.println("This is Volvo"); } public void sayStr() { System.out.println(super.toString()); //--方法调用 } } public class TestClass { public static void main(String[] args) { Volvo volvo = new Volvo("Volvo"); System.out.println(volvo.toString()); } }output: This is Car This is Volvo Volvo
4.成员变量、方法的覆盖
4.1 成员变量的覆盖
(1). 当子类覆盖父类的成员变量时,父类方法使用父类的成员变量,子类方法使用子类的成员变量。
这个听起来很容易理解的一回事,但是实际使用过程中很多人容易搞混:尤其是在多态的时候,调用一个被继承的方法,该方法访问是一个被覆盖的成员m,那么方法中到底是访问了父类的成员还是子类的成员m?结论是,若实际调用的是父类的方法,就使用了父类的该成员m,若实际调用的是子类的方法,就使用子类的成员m,记住一句,每个类使用成员都相当于在前面加了 一个this指针。
4.2 成员方法的覆盖
(1). 方法的返回类型可以是父类也可以是父类的子类(协变类型)
class Car { private String str; Car(String str) { this.str = str; System.out.println("This is Car"); } public Car getCar(){ return new Car("Car"); } } class Volvo extends Car { Volvo(String str) { super(str); System.out.println("This is Volvo"); } @Override public Volvo getCar() { //--协变类型 return new Volvo("Volvo"); } } public class TestClass { public static void main(String[] args) { Volvo volvo = new Volvo("Volvo"); volvo.getCar(); } }output: This is Car This is Volvo This is Car This is Volvo
class SubClass1 extends SuperClass { SubClass1(int number) { super(number); } } class SubClass2 extends SuperClass { private int number; SubClass2(int number) { super(number); } } public class SubClass extends SuperClass { private int number; SubClass(int number) { super(number); } public int getNumber() { number++; return number; } public static void main(String[] args) { SuperClass s = new SubClass(20); SuperClass s1 = new SubClass1(20); SuperClass s2 = new SubClass2(20); System.out.println(s.getNumber()); System.out.println(s1.getNumber()); System.out.println(s2.getNumber()); //结论一:多态时,当子类覆盖了父类的方法,使用子类覆盖的方法 //结论二:当子类覆盖父类的成员变量时,父类方法使用的是父类的成员变量,子类方法使用的是子类的成员变量 } }output:
1
21
21
5.question
《thinking in java》上的一个例子,它上面有一些解释。但是自己没有完全理解。感觉要看jvm后才能完全明白,先立个flag在这吧
class Car { Car() { run(); } void run() {} } class Volvo extends Car { private int count; Volvo(int count) { this.count = count; run(); } @Override void run() { System.out.println("Count:" + count); } } public class TestClass { public static void main(String[] args) { Volvo volvo = new Volvo(1); } }output: 0 1