一.继承的优点
1:提高了代码的复用性。
2:让类与类之间产生了关系,提供了另一个特征多态的前提。
二.继承的特点
1.java中的继承是单继承的。
2.但允许多重继承,a继承b,b继承c,a就继承c。
三.super
1.定义:代表是子类所属的父类中的内存空间引用。
2.super方法只能在构造方法中调用。
3.在子类的构造方法中调用super方法时,super方法必须是该方法中的第一条语句。
4.一个构造方法中只能有一个super方法。
5.可用super.属性或方法的形式调用父类的属性或方法。
6.super()与this()不能同时出现在一个构造方法中。
7.super.getClass()的问题
/**
* date:2017年6月11日10:33:32
* target:super.getClass()方法。
* @author ypy
*/
class A {
public void m1() {
System.out.println(super.getClass().getName());//等价于getClass().getName()
//因为Object类中的getClass()定义为final,子类不能覆盖
//所以子类中调用的getClass()方法其实就是调用的父类中的getClass()方法
}
public void m2() {
System.out.println(getClass().getSuperclass().getName());//此方法才能返回父类
}
}
public class Super_getClass {
public static void main(String[] args) {
A a = new A();
a.m1();
a.m2();
}
}
/*
*************** jdk1.8运行结果***************
dao.A
java.lang.Object
*/
四.合成(在类中创建另一个类的对象)与继承?
1.“包含”关系就用合成,“属于”关系就用继承,继承很少用,只有必须用“上溯造型”时才用继承。
2. 为什么多用组合,少用继承?
第一、子类对父类的继承是全部的公有和受保护的继承,这使得子类可能继承了对子类无用甚至有害的父类的方法。换句话说,子类只希望继承父类的一部分方法,怎么办?
第二、实际的对象千变万化,如果每一类的对象都有他们自己的类,尽管这些类都继承了他们的父类,但有些时候还是会造成类的无限膨胀。
第三、 继承的子类,实际上需要编译期确定下来,这满足不了需要在运行内才能确定对象的情况。而组合却可以比继承灵活得多,可以在运行期才决定某个对象。
五.继承中父类对象的初始化
1.继承发生时,就在子类中封装了一个父类对象,为了正确初始化父类对象,只能在构造方法中对其初始化。
2.如果父类的构造方法为默认的构造方法,子类中默认的构造方法就会自动的发出对父类构造方法的调用。
3.如果父类的构造方法含有参数,子类中就必须自己写构造方法,而且用super调用父类的构造方法。
(先调用父类的构造方法,再调用子类的构造方法)
六.继承中一个变量的初始化顺序
/** * date:2017年4月20日16:03:29 * target:继承中构造方法执行顺序的一些问题。 * @author ypy * conclusion: * 执行顺序: * main->new RoundGlyph的对象(此时,在采取其他任何操作之前,为对象分配的存储空间初始化成二进制零,radius=0) * ->父类的构造方法->子类重写的draw方法(此时的radius还为0)->对radius赋值1->子类的构造方法 */ abstract class Glyph { abstract void draw(); Glyph() { System.out.println("Glyph() before draw()"); draw(); System.out.println("Glyph() after draw()"); } } class RoundGlyph extends Glyph { private int radius = 1;//如果这个属性是static的,那么输出结果就为RoundGlyph.draw(), radius = 1 //因为在类加载的时候就为其赋值为1了 RoundGlyph(int r) { radius = r; System.out.println("RoundGlyph.RoundGlyph(), radius = " + radius); } @Override void draw() { System.out.println("RoundGlyph.draw(), radius = " + radius); } } public class JiCheng_5 { public static void main(String[] args) { new RoundGlyph(5); } } /* * *************** jdk1.8运行结果*************** Glyph() before draw() RoundGlyph.draw(), radius = 0 Glyph() after draw() RoundGlyph.RoundGlyph(), radius = 5 */
七.继承中的收尾工作
在构建finalize收尾工作时,应该首先执行子类的收尾,再是父类的收尾。
这是由于子类的收尾可能调用父类中相同的方法,要求父类组件仍然处于活动状态。
/**
* date:2017年4月20日09:40:51
* target:继承中的收尾工作。
* @author ypy
* conclusion:
* 在构建finalize收尾工作时,应该首先执行子类的收尾,再是父类的收尾。
* 这是由于子类的收尾可能调用父类中相同的方法,要求父类组件仍然处于活动状态。
*/
class DoBaseFinalization {
public static boolean flag = true;
}
class Father {
public Father() {
System.out.println("father!");
}
@Override
protected void finalize() throws Throwable {
System.out.println("father finalize!");
}
}
class Childen extends Father {
public Childen() {
System.out.println("childen!");
}
@Override
protected void finalize() throws Throwable {
System.out.println("childen finalize!");
if (DoBaseFinalization.flag) {
super.finalize();
}
}
}
public class JiCheng_4 {
public static void main(String[] args) {
new Childen();
System.runFinalizersOnExit(true);//这里如果调用System.gc()方法时不会执行父类的finalize()
}
}
/* *************** jdk1.8运行结果***************
father!
childen!
childen finalize!
father finalize!
*/