不奢望岁月静好 只希望点滴积累

0%

Java类的加载和继承实现

类方法 & 实例方法

1
2
3
4
5
6
7
8
9
类方法:(静态方法) static修饰、可以通过类名直接访问、
实例方法: 无static修饰、必须通过创建的实例才能访问

类变量和实例变量同理

实例方法可以直接访问实例变量 ?
因为在实例方法中、有一个隐含的参数(当前操作的对象本身)
1. 类方法只能调用类方法、访问类变量, 不能访问实例方法和实例变量
2. 实例方法可以访问类方法、类变量、实例方法、实例变量

可以将类看成自定义数据类型

Note

1
2
3
4
5
6
7
8
9
10
11
12
13
1. 定义一个类本身、什么都不会做、不会分配内存、也不会执行代码
2. 声明变量本身只分配存放位置的内存空间、这块空间还未指向任何实际内容
3. p = new Point();
1) 分配内存、以存储新对象的数据(这个对象的属性、包括实例变量x|y)
2) 给实例变量设置默认值、int->0 boolean->false char->\u000 refer->null

4. 修改变量默认值
1) 定义的同时、初始化 private int x = 1;
2) 初始化代码块 private int y; {y=2}
3) 构造方法
调用顺序 1) -> 2) -> 3) 所以、若多种方式定义了默认值、前边的会被后边的覆盖

5. final修饰类变量、实例变量、表示变量只能被赋值一次、final也可以修饰实例方法

类和对象的生命周期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1. 程序运行时、第一次通过new创建一个类的对象的时候、or 直接通过类名访问类变量/类方法的时候、
Java会讲类加载进内场、为这个类分配一块空间、保护类的定义、有哪些变量和方法、
还有类的静态变量、并对静态变量赋初值

类加载进内存后一般不会释放、直到程序结束、一般情况下、只加载一次(静态变量在内存中只存在一份)

2. 对象 每次new、都会产生一个新的实例、会有一份独立的实例变量
每个对象除了保存实例变量的值、还保存着对应类的地址、即: 通过对象可以知道类、就能访问到类的变量和方法
实例方法可以理解为多了this参数的静态方法

对象的释放是被Java的垃圾回收机制管理的
a. 保存地址的部分分配在桟上、函数调用入栈就分配、出栈就释放
b. 保存内容的部分分配在堆上、无活跃变量指向对象的时候(已加载的类的类变量和桟中所有的变量)、
就可能被释放

类继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1. java 使用extends表明继承关系、一个类只有一个父类
2. 子类不可访问父类的私有属性和方法、可以访问 protectedpublic

3. 向上转型: 子类对象赋值给父类引用变量(转换为父类类型)、

4. 多态: 变量shape可以引用任何Shape子类类型的对象、即一种类型的变量、可以引用多种实际类型对象
变量shape有两种类型、类型Shape: 称为shape的静态类型、circle/line/arrowLine 称为shape的动态类型

5. 动态绑定: shapes[i].draw() 调用的是其对应动态类型的draw方法、称为方法的动态绑定

6. 若父类只有一个带参数的构造方法、则所有子类都必须通过super调用base的带参构造

7. 若父类构造方法调用了可被重写的方法、可能会出现意想不到的结果

8. 静态绑定: 在类的内部、访问的是当前类
在类的外部、要看如何访问、静态类型是父类、则访问的是父类

9. 静态变量和方法、一般通过类名直接访问、也可以通过实例对象来访问

10. 在有多个重名函数的时候、首先按照参数类型进行匹配、然后才看变量的动态类型、进行动态绑定

11. 模板方法: 在父类定义一个实现的模板、具体实现由子类提供

12. 子类可以升级父类的可见性、不可降低

类加载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
在Java中、类的加载时将类的相关信息加载到内存、Java是动态加载的、第一次使用时才会加载
加载一个类时、会查看其父类是否已加载、若没有、会加载其父类

类初始化代码:
1. 定义静态变量时的赋值语句
2. 静态初始化代码块

实例初始化代码:
1. 定义实例变量时的赋值语句
2. 实例初始化代码块
3. 构造方法

类加载过程:
1. 分配内存保存类的信息
2. 给类变量赋默认值
3. 加载父类
4. 设置父子关系
5. 执行类初始化代码(先执行父类 -> 子类、不过父类执行时、子类静态变量是有值的、默认值)

内存分为堆(存放动态分配的对象)和桟(存放函数的局部变量)、还有一个内存区: 方法区(存放类的信息)

创建对象:
1. 分配内存
包括本类和父类的所有实例变量、但不包括任何静态变量
实例化代码从父类开始、再执行子类
但: 在任何类执行初始化代码之前、所有的实例变量都已设置完默认值

2. 对所有的实例变量赋默认值
3. 执行实例初始化代码

**Note**
每个对象除了保存类的实例变量之外、还保存着实际类信息的引用

虚方法表

1
2
在类加载的时候、为每个类创建一个表、包括类的对象所有动态绑定的方法及地址、包括父类的方法
但同一个方法只有一条记录、子类重写之后就只会保留子类的

疑问:

1
2
3
4
5
6
7
8
Q. 实例变量的初始化是在new的时候进行的、类变量的初始化呢 ?(MyNumber.class)
A. Java对静态类的初始化
1) 为类里边的静态变量分配内存空间、并赋初值
2) 按照初始化的代码顺序对类变量进行初始化

Q: 父子类、同名静态变量在内存中如何保存 ?
同名实例变量呢 ?
A: 对于子类来说、会保存两份、静态类型是哪个的时候、访问的就是哪个

参考:
https://mp.weixin.qq.com/s/u_WmkE5meMWuZ81G5gHhBQ

代码整理:
https://github.com/niujing1/javaLearn/tree/master