Java学习之继承中的执行顺序详解

来源:互联网 发布:上海网络信用借贷 编辑:程序博客网 时间:2024/05/03 03:23
代码块(理解)
(1)用{}括起来的代码。
(2)分类:
A:局部代码块
用于限定变量的生命周期,及早释放,提高内存利用率。
B:构造代码块
把多个构造方法中相同的代码可以放到这里,每个构造方法执行前,首先执行构造代码块。

C:静态代码块

static{}对类的数据进行初始化,仅仅只执行一次。

(3)静态代码块,构造代码块,构造方法的顺序问题?

静态代码块 > 构造代码块 > 构造方法

class Student {static {System.out.println("Student 静态代码块");}{System.out.println("Student 构造代码块");}public Student() {System.out.println("Student 构造方法");}}class StudentDemo {static {System.out.println("studentDemo静态代码块");}public static void main(String[] args) {System.out.println("我是main方法");Student s1 = new Student();Student s2 = new Student();}}
运行结果如下:

/*写程序的执行结果。<span style="font-family: Arial, Helvetica, sans-serif;">studentDemo静态代码块</span>我是main方法Student 静态代码块Student 构造代码块Student 构造方法Student 构造代码块Student 构造方法*/

继承(掌握)
(1)把多个类中相同的成员给提取出来定义到一个独立的类中。然后让这多个类和该独立的类产生一个关系,
  这多个类就具备了这些内容。这个关系叫继承。
(2)Java中如何表示继承呢?格式是什么呢?
A:用关键字extends表示
B:格式:
class 子类名 extends 父类名 {}
(3)继承的好处:
A:提高了代码的复用性
B:提高了代码的维护性
C:让类与类产生了一个关系,是多态的前提
(4)继承的弊端:
A:让类的耦合性增强。这样某个类的改变,就会影响其他和该类相关的类。
原则:低耦合,高内聚。
耦合:类与类的关系
内聚:自己完成某件事情的能力
B:打破了封装性
(5)Java中继承的特点
A:Java中类只支持单继承
B:Java中可以多层(重)继承(继承体系)
(6)继承的注意事项:
A:子类不能继承父类的私有成员
B:子类不能继承父类的构造方法,但是可以通过super去访问
C:不要为了部分功能而去继承
(7)什么时候使用继承呢?
A:继承体现的是:is a的关系。
B:采用假设法
(8)Java继承中的成员关系
A:成员变量
a:子类的成员变量名称和父类中的成员变量名称不一样,直接访问
b:子类的成员变量名称和父类中的成员变量名称一样,这个怎么访问呢?
子类的方法访问变量的查找顺序:就近原则
在子类方法的局部范围找,有就使用。
在子类的成员范围找,有就使用。
在父类的成员范围找,有就使用。
找不到,就报错。
B:构造方法
a:子类的构造方法默认会去访问父类的无参构造方法

1:子类中所有的构造方法默认都会访问父类中空参数的构造方法
2:为什么呢?
因为子类会继承父类中的数据,可能还会使用父类的数据。
所以,子类初始化之前,一定要先完成父类数据的初始化。父类的初始化是调用方法区中的构造方法进行初始化,不会创建父类对象,对象是要new关键字来创建的

new关键字有两个作用。一是分配内存,

创建对象。二是调用构造方法,完成对象的初始化工作。完成这两步之后,才算创建了一个完整的Java对象。

所以new子类的时候,调用父类的构造方法不是创建了一个父类对象,而是只对它的数据进行初始化,那么父类这些数据存储在哪里呢?通俗说子类对象内存区域中会划一部分区域给父类的数据的存储,即子类对象内存中封装了父类的初始化数据,创建子类对象时,父类的数据就是子类的对象的一部分,不存在独立的父类的对象,所有的东西在一起才是一个完整的子类的对象注意:子类每一个构造方法的第一条语句默认都是:super();

class Son extends Father {public Son() {//super();System.out.println("Son的无参构造方法");}public Son(String name) {//super();System.out.println("Son的带参构造方法");}}class ExtendsDemo6 {public static void main(String[] args) {//创建对象Son s = new Son();System.out.println("------------");Son s2 = new Son("林青霞");}}
运行结果:

Father的无参构造方法Son的无参构造方法------------Father的无参构造方法Son的带参构造方法
b:父类中如果没有无参构造方法,怎么办?
子类通过super去明确调用带参构造(子类用super();调用父类构造方法只能在构造方法中的第一行调用)
子类通过this调用本身的其他构造,但是一定会有一个去访问了父类的构造
习惯:最好每次都让父类提供无参构造

class Father {/*public Father() {System.out.println("Father的无参构造方法");}*/public Father(String name) {System.out.println("Father的带参构造方法");}}class Son extends Father {public Son() {super("随便给");System.out.println("Son的无参构造方法");//super("随便给");}public Son(String name) {//super("随便给");this();System.out.println("Son的带参构造方法");}}class ExtendsDemo7 {public static void main(String[] args) {Son s = new Son();System.out.println("----------------");Son ss = new Son("林青霞");}}
运行结果:

Father的带参构造方法Son的无参构造方法----------------Father的带参构造方法Son的无参构造方法Son的带参构造方法
C:成员方法
a:子类的成员方法和父类中的成员方法名称不一样,直接访问
b:子类的成员方法和父类中的成员方法名称一样,这个怎么访问呢?
通过子类对象访问一个方法的查找顺序:就近原则
在子类中找,有就使用
在父类中找,有就使用
找不到,就报错
(9)两个面试题:
A:Override和Overload的区别?Overload是否可以改变返回值类型?可以
B:this和super的区别和各自的作用?

this代表本类对应的引用。

super代表父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)

怎么用呢?
A:调用成员变量
this.成员变量 调用本类的成员变量
super.成员变量 调用父类的成员变量
B:调用构造方法
this(..参数.) 调用本类的构造方法
super(..参数.) 调用父类的构造方法
C:调用成员方法
this.成员方法 调用本类的成员方法
super.成员方法 调用父类的成员方法
(10)数据初始化的面试题
A:一个类的初始化过程

/*看程序写结果:A:成员变量就近原则B:this和super的问题this访问本类的成员super访问父类的成员C:子类构造方法执行前默认先执行父类的无参构造方法D:一个类的初始化过程成员变量进行初始化默认初始化显示初始化构造方法初始化结果:fuzi302010*/class Fu{public int num = 10;public Fu(){System.out.println("fu");}}class Zi extends Fu{public int num = 20;public Zi(){System.out.println("zi");}public void show(){int num = 30;System.out.println(num); //30System.out.println(this.num); //20System.out.println(super.num); //10}}class ExtendsTest {public static void main(String[] args) {Zi z = new Zi();z.show();}}


B:子父类的构造执行过程

/*看程序写结果:A:一个类的静态代码块,构造代码块,构造方法的执行流程静态代码块 > 构造代码块 > 构造方法B:静态的内容是随着类的加载而加载静态代码块的内容会优先执行C:子类初始化之前先会进行父类的初始化结果是:静态代码块Fu静态代码块Zi构造代码块Fu构造方法Fu构造代码块Zi构造方法Zi*/class Fu {static {System.out.println("静态代码块Fu");}{System.out.println("构造代码块Fu");}public Fu() {System.out.println("构造方法Fu");}}class Zi extends Fu {static {System.out.println("静态代码块Zi");}{System.out.println("构造代码块Zi");}public Zi() {System.out.println("构造方法Zi");}}class ExtendsTest2 {public static void main(String[] args) {Zi z = new Zi();}}


C:分层初始化

/*看程序写结果:A:成员变量的问题int x = 10; //成员变量是基本类型Student s = new Student(); //成员变量是引用类型B:一个类的初始化过程成员变量的初始化默认初始化(给默认的值)显示初始化(给我们给变量赋的值)构造方法初始化C:子父类的初始化(分层初始化)先进行父类初始化,然后进行子类初始化。结果:YXYZ问题:虽然子类中构造方法默认有一个super()初始化的时候,不是按照那个顺序进行的。而是按照分层初始化进行的。它仅仅表示要先初始化父类数据,再初始化子类数据。*/class X {Y b = new Y();X() {System.out.print("X");}}class Y {Y() {System.out.print("Y");}}public class Z extends X {Y y = new Y();Z() {//superSystem.out.print("Z");}public static void main(String[] args) {new Z(); }}



1 0
原创粉丝点击