黑马程序员-继承 子类的实例化和final关键字*

来源:互联网 发布:淘宝团购提醒在哪里 编辑:程序博客网 时间:2024/06/05 20:08

------- android培训、java培训、期待与您交流! ----------

当多个类中存在相同的属性和行为时,将这些内容抽取到单独一个类中,那么多个类不需要再定义这些属性和行为,只需要

继承单独的那个类即可。多个类称为子类,单独这个类称为父类或超类。
子类可以直接访问父类中的非私有的属性和行为。
通过extends关键字让类与类之间产生继承关系。
继承的出现提高代码的复用性,并提供了多态的前提。


java中只支持单继承,不支持多继承,因为多继承容易带来安全隐患:
当功能内容不同时,子类对象不确定要运行哪一个。但java保存了这种机制,通过多实现来完成。
但支持多层继承体系。
想要使用体系,先查阅体系父类的描述,因为父类中的定义的是该体系的共性内容。
定义继承时,不能为了获取某个类中的属性或行为而定义继承,必须要确定两个类间有"is a "的关系,否则没有继承关系。


为什么在具体调用时,要创建子类对象呢?
1.因为有可能父类不能创建的对象
2.创建子类对象可以有共性和特有属性即方法。


当子类创建对象时,会先加载父类的字节码文件,然后再加载子类的字节码文件。
在堆内存中会同时存在父类和子类的相同属性,在方法区中同时存在父类和子类的方法。
super和this的使用方法基本相同,this代表本类对象的引用,super代表父类对象的引用。
当父类中定义非私有属性时,在建立子类对象时,子类中没有定义该属性,那么调用该属性时,可以同时用this或者super来调用
该属性,如this.name或者super.name,可以理解为子类继承父类的该属性,或者this和super都指向了子类对象。


函数的另一个特性:覆盖
子类继承父类时,沿袭了父类的功能,子类虽然具备该功能,但功能的具体内容有所改变,可以定义和父类相同的功能方法,来
保留父类功能定义,并重写功能内容。实现子类的特有功能。称之为函数的覆盖。
注意:子类覆盖父类,必须保证子类的访问权限大于或等于父类,且父类的权限不能为私有。静态只能覆盖静态。


子类的实例化过程
在对子类对象初始化时,父类的构造函数也会运行。因为子类的构造函数第一行有一条隐式的语句super();
即会访问父类中的空参数的构造函数。而且子类中所有的构造函数默认第一行都是super();

class Fu{int num = 4;Fu(){System.out.println("fu run"+num);}Fu(int num){this.num = num;System.out.println("fu run..."+num);}}class Zi extends Fu{//int num ;当子类中没有定义num变量时,子类初始化时会沿袭父类num的值int num;/*当子类中也定义了num变量时,子类构造函数初始化时,通过super()调用父类构造函数而父类构造函数中调用了num  时,父类构造函数中的num调用的是父类中的num值,子类构造函数中调用的num是子类中的num值。因为在构造函数初始化  前,对象已经进行特有属性的显示初始化了。*/Zi(){System.out.println("zi run"+num);}Zi(int num){//super();默认调用父类空参数构造函数//this();如果有this()时,会先调用本类中的空参数构造函数,在调用本类空参数构造函数时,又会先调用父类的空参数构造函数。//super(num);如果自定义super语句指定父类的具体构造函数,就会调用对应父类的构造函数。this.num = num;System.out.println("zi fun..."+num);}}class ExtendsDemo {public static void main(String[] args) {Zi z1 = new Zi();Zi z2 = new Zi(5);}}

为什么子类一定要访问父类中的构造函数:
因为父类中的数据子类可以直接获取,子类在对象初始化前需要参考父类是如何对这些数据进行初始化的,所以要先访问父类的
构造函数。可以在子类构造函数中自定义super语句来指定访问父类的具体构造函数。
注意:super语句一定要定义在子类构造函数的第一行。


结论:
子类的所有构造函数,默认都会访问父类中的空参数的构造函数。
因为子类每一个构造函数内的第一行默认都会有一句隐式的super();
当父类中没有空参数的构造函数时,子类必须手动通过super语句来指定访问父类中的构造函数。
当然子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。
子类中至少有一个构造函数会访问父类中的构造函数。



final:最终,作为一个修饰符。
1.final可以修饰类,也可以修饰方法,变量。
2.final修饰的类不能被继承。为了避免被子类复写。
3.final修饰的方法不能被复写。
4.final修饰的变量时一个常量只能复制一次,既可以修饰成员变量,也可以修饰局部变量。
当在描述事物时,一些数据的出现值是固定的,这时为了增强阅读性,给这些值起个名字,方便与阅读。
而这个值不需要改变,所以加上final修饰。作为常量,全部大写,单纯间用_连接。
5.内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。
6.final只对引用的”值“(即内存地址 )有效,它迫使引用只能指向初始指向的那个对象,改变它的指向会
导致编译期错误。至于它所指向的对象的变化,final是不负责的。

final StringBuffer sb1 = new StringBuffer("aaa");
final StringBuffer sb2 = new StringBuffer("bbb");
sb1=sb2;//编译不通过,无法为最终变量分配地址值
原创粉丝点击