学习面向对象内容的三条主线
- Java类及类的成员:(重点)属性、方法、构造器;(熟悉)代码块、内部类
- 面向对象的特征:封装、继承、多态、(抽象)
- 其他关键字的使用:this、super、package、import、static、final、interface、abstract等
对象内存解析
对象在内存中的分配涉及到的内存结构(理论)
- 栈(stack): 方法内定义的变量
- 堆(heap) : new出来的结构(比如:数组实体,对象实体),包括对象中的属性
- 方法区(method area) : 存放类的模板。比如:Person类的模板
类中对象的内存解析
2.1 创建类的一个对象
2.2 创建类的多个对象
:::info
强调1:
:::
Person p1 = new Person();
Person p2 = new Person();
p1.age = 10;
p2.age = 20;
:::info
创建类的多个对象时,每个对象在堆空间中有一个实体,
每个对象实体中保存着一份类的属性
如果修改某一个对象的某属性时,不会影响其他对象此属性的值
:::
没有new,就不会信开辟堆空间
p1和p3共用一个地址
两个变量,指向同一个对象
强调2:声明类的两个变量
Person p1 = new Person();
Person p3 = p1;
p3.age = 20; // p1.age = 20;
此时的p1,p3两个变量指向了堆空间中同一个对象实体,
两个变量保存的地址值相同,
如果通过某一个变量修改对象的属性时,会导致另一个对象变量此属性的值改变
2.3 对象调用方法的过程(在"03-类的成员之二:方法"中讲解)
类的成员之一:属性
属性的几个称谓:成员变量、属性、field(字段、域)
1. 变量的分类
- 角度一:按照数据类型来分:基本数据类型(8种)、引用数据类型(数组、类、接口、枚举、注解、记录)
- 角度二:按照变量在类中声明的位置的不同:成员变量(或属性)、局部变量(方法内、方法形参、构造器内、构造器形参、代码块内等)
2. 成员变量 vs 局部变量
- 在方法体外,类体内声明的变量称为成员变量。
- 在方法体内部等位置声明的变量称为局部变量。
其中,static可以将成员变量分为两大类,静态变量和非静态变量。其中静态变量又称为类变量,非静态变量又称为实例变量或者属性。接下来先学习实例变量。
成员变量 与 局部变量 的对比
- 相同点
- 变量声明的格式相同: 数据类型 变量名 = 初始化值
- 变量必须先声明、后初始化、再使用。
- 变量都有其对应的作用域。只在其作用域内是有效的
- 不同点
区别 | 局部变量 | 成员变量 |
---|---|---|
声明位置和方式 | 在方法体中、方法的形参列表、代码块中 | 在类中 && 方法外 |
在内存中存储的位置 | 栈 | 堆 |
生命周期 | 和方法调用的生命周期一样,每一次方法被调用而在存在,随着方法执行的结束而消亡,而且每一次方法调用都是独立 | 和对象的生命周期一样,随着对象的创建而存在,随着对象被GC回收而消亡, 而且每一个对象的实例变量是独立的 |
作用域 | 出了作用域就不能使用 | 通过对象就可以使用,本类中直接调用,其他类中“对象.实例变量” |
修饰符 | final | public,protected,private,final,volatile,transient等 |
默认值 | 没有,必须手动初始化。 其中的形参比较特殊,靠实参给它初始化 |
有默认值 |
类的成员之二:方法
方法声明的格式
权限修饰符 [其他修饰符(static/final/abstract)] 返回值类型 方法名(形参列表) [thorws 异常] {
// 方法体
}
// []中的内容不是必须的
修饰符:
可选的。方法的修饰符也有很多,例如:public、protected、private、static、abstract、native、final、synchronized等,后面会一一学习。
- 其中,权限修饰符有public、protected、private。在讲封装性之前,我们先默认使用pulbic修饰方法。
- 其中,根据是否有static,可以将方法分为静态方法和非静态方法。其中静态方法又称为类方法,非静态方法又称为实例方法。咱们在讲static前先学习实例方法。
返回值类型
调用完此方法时,是否需要返回一个结果
- 无返回值类型:void表示即可
- 有具体的返回值类型:需要指明返回的类型,基本数据类型或引用类型
- 需要在方法内部使用return + 返回值类型的变量或常量
- 需要在方法内部使用return + 返回值类型的变量或常量
形参列表
属于局部变量,且可以声明多个
表示完成方法体功能时需要外部提供的数据列表。可以包含零个,一个或多个参数。
- 无论是否有参数,()不能省略
- 如果有参数,每一个参数都要指定数据类型和参数名,多个参数之间使用逗号分隔,例如:
- 一个参数: (数据类型 参数名)
- 二个参数: (数据类型1 参数1, 数据类型2 参数2)
- 参数的类型可以是基本数据类型、引用数据类型
关键字return
作用:
- 结束一个方法
- 结束方法的同时,返回数据给方法的调用者
方法调用内存分析
- 方法没有被调用的时候,都在方法区中的字节码文件(.class)中存储。
- 方法被调用的时候,需要进入到栈内存中运行。方法每调用一次就会在栈中有一个入栈动作,即给当前方法开辟一块独立的内存区域,用于存储当前方法的局部变量的值。
- 当方法执行结束后,会释放该内存,称为出栈,如果方法有返回值,就会把结果返回调用处,如果没有返回值,就直接结束,回到调用处继续执行下一条指令。
- 栈结构:先进后出,后进先出。
eat()方法调用结束后就会弹出栈
对象数组
数组的元素可以是基本数据类型,也可以是引用数据类型。
当元素是引用类型中的类时,我们称为对象数组。
案例
定义类Student,包含三个属性:学号number(int),年级state(int),成绩score(int)。 创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。
问题一:打印出3年级(state值为3)的学生信息。
问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
package oop4_arrays;
public class StudentTest {
public static void main(String[] args) {
Student[] students = new Student[20];
for (int i = 0; i < students.length; i++) {
students[i] = new Student