我终究是打算挑一门编程语言学习了,因为我隐隐约约地发觉我想做的某些事情需要我会 coding。之前学了点 py 皮毛,但似乎没啥用。遂转至 Java 学习,目前就是这么个进度。会系统性记笔记的,希望我不会半途而废。
类与对象
类负责创建对象。类拥有属性和行为。
对象是是由类创造出来的一个具体存在,可以直接使用,由哪一个类创建出来的对象,就拥有在哪一个类中定义的属性和方法。
打比方:我看许多人把这俩的关系比作““模板/实例””,我个人就当作是 Docker 镜像与容器的关系了。
封装
对象代表什么,就要封装对应的数据,并提供数据对应的行为。
打比方:对象人把对象门关上了,那么关门,是人的方法,还是门的方法?答案是后者。
Private 关键字
权限修饰符,可以修饰成员变量和方法,被 Private 修饰的成员只能在本类中被访问。
变量使用 private 修饰,赋值方法使用 public 修饰并加上一些判断,可以实现输入参数过滤。
就近原则
就近原则是指当Java虚拟机(JVM)执行方法调用或变量访问时,它会首先在当前作用域内查找匹配的方法或变量。如果当前作用域没有找到,它会继续向外层作用域逐级查找,直到找到为止。
this 关键字
this是一个特殊的关键字,它引用了当前对象本身。在类的非静态方法中,可以使用this来指代调用该方法的对象。
public class Test {
private int a;
public void method() {
int a = 10;
System.out.println(a);
System.out.println(this.a);
}
}
调用 method 方法应该会以依次打印 10、0。
构造方法
声明与特点
也叫做构造器、构造函数。
作用:在 Java 中,构造方法(Constructor)是一种特殊的方法,用于初始化新创建的对象。当使用 new 关键字创建一个类的实例时,系统会自动调用该类的构造方法,为对象的属性赋初始值或执行必要的准备工作。
[访问修饰符] 类名([参数列表]) {
// 初始化代码
}
- 方法名必须与类名完全相同(包括大小写)。
- 没有返回值类型,甚至连
void都不能写。 - 可以有
0个、1个或多个参数,支持重载(Overload)。 - 不能被
static、final、abstract、synchronized修饰。 - 不能被继承,但子类可以通过
super()调用父类的构造方法。
默认构造方法
- 如果一个类中没有显式定义任何构造方法,编译器会自动提供一个无参的默认构造方法,其方法体为空,访问权限与类的访问权限一致。
- 一旦定义了任意一个构造方法,默认构造方法便不再生成。
说实话这里我想了有一会才整明白这玩意儿有什么用。缺失了参数的对象应该是不能先直接 new 出来的。例如:
public class Student {
// 没有定义构造方法 → 默认无参构造存在
private String name;
}
// 可以:Student s = new Student();
public class Student {
private String name;
public Student(String name) { // 显式定义
this.name = name;
}
}
// 此时默认无参构造不再提供,Student s = new Student(); 会编译错误
如果一个对象的属性是事先不知道而依赖后续键盘录入的,就只能先指定一个空参构造方法。
推荐的使用方法
无论是否适用,都手动书写无参构造和带全部参的构造方法。
标准的 JavaBean 类
JavaBean 是一种符合特定编码规范的 Java 类,主要用于封装数据,被视为可复用的组件。它并非新的语法或框架,而是一种约定俗成的设计模式。
- 类名需要见名知意
- 成员变量使用 private 修饰
- 提供至少两个构造方法:无参的构造方法、带全部参的构造方法
- 成员方法:提供每一个成员变量对应的 setXxx()/getXxx();如果还有其他行为,也要写上
JavaBean 是一种轻量级的组件规范,强调可复用性、可读性和工具支持。通过统一的对象创建(无参构造)和属性访问方式(getter/setter),它成为 Java 生态中数据封装和传递的标准形式,至今仍被广泛使用。
三种情况下的对象内存
Java 内存分配:
- 栈
- 堆
- 方法区
本地方法栈寄存器
(还没学到)
一个对象
- 加载字节码文件进方法区
- 申明局部变量
- 在堆中开辟一块空间(含成员方法的地址)
- 默认初始化(例如 String null、int 0)
- 显式初始化
- 构造方法初始化
- 将堆内存中的地址值赋值给局部变量
至此,一个对象创建完毕。随后方法正常进栈出栈。
内存图:
栈内存 堆内存
+-------+ +----------------+
| p | ------> | Person 对象 |
+-------+ | name = null |
| age = 0 |
+----------------+
两个对象
基本一致。内存图:
栈内存 堆内存
+-------+ +-----------------+
| p1 | ------> | Person 对象1 |
+-------+ | name = null |
| age = 0 |
+-----------------+
+-------+ +-----------------+
| p2 | ------> | Person 对象2 |
+-------+ | name = null |
| age = 0 |
+-----------------+
两个引用指向同一对象
栈内存 堆内存
+-------+ +-----------------+
| p1 | ------->| Person 对象 |
+-------+ | | name = null |
| | age = 0 |
+-------+ | +-----------------+
| p2 | ---/
+-------+
- p2 = p1 是将 p1 中存储的地址值复制给 p2,并未创建新对象。
- 此时两个引用指向堆中的同一块内存。
- 通过 p1 修改对象属性(如 p1.setName("张三")),再通过 p2.getName() 获取到的是修改后的值——因为操作的是同一个对象。
基本数据类型与引用数据类型
基本数据类型:
- 整数
- 浮点
- 布尔
- 字符
引用数据类型是除了上述数据类型以外的所有数据类型。
基本数据类型的值存储在自己的空间里。而引用数据类型的值存储在其他空间中,自己空间里只存储地址值。
内存角度的 this 关键字
this 的本质:this 中存放的是当前对象在堆中的内存地址,与通过对象名访问的是同一份数据。
this 的作用:区分实例变量与局部变量。
成员变量与局部变量
释义
- 成员变量:类中方法外的变量
- 局部变量:方法中的变量
区别
| 「区别」 | 「成员变量」 | 「局部变量」 |
| 类中位置不同 | 类中、方法外 | 方法内、方法申明上 |
| 默认初始化值 | 有 | 无 |
| 内存位置不同 | 堆内存 | 栈内存 |
| 生命周期 | 随着对象的创建而存在,随着对象的消失而消失 | 随着方法的调用而存在,随着方法结束而消失 |
| 作用域 | 整个类中有效 | 当前方法中有效 |
版权申明
文章封面:コーラ (id=53403181)
Comments NOTHING