java(上)
模块一
1.JDK,JRE,JVM
知识点 |
核心内容 |
易混淆点 |
JDK定义 |
Java Development Kit(Java开发工具包),包含开发所需全部工具 |
JDK包含JRE的关系容易混淆 |
JRE定义 |
Java Runtime Environment(Java运行环境),包含JVM和核心类库 |
JRE与JDK的包含关系 |
JVM作用 |
Java虚拟机,实现跨平台运行的核心组件 |
JVM在JRE中的位置 |
开发工具 |
包含javac(编译)、java(运行)、jdb(调试)、jhat(内存分析)等工具 |
各工具的具体用途区分 |
版本变化 |
JDK 9开始取消独立JRE目录,采用模块化技术优化运行时环境 |
新旧版本目录结构差异 |
模块化优势 |
允许创建最小运行时环境,提高运行效率,减少资源占用 |
与传统JRE部署方式的对比 |
安装建议 |
只需安装JDK即可获得完整开发环境(包含JRE和JVM) |
JDK版本选择注意事项 |
2.API文档注释
知识点 |
核心内容 |
重点 |
文档注释的作用 |
通过Javadoc生成API文档,帮助他人快速理解代码功能、类用途及方法说明 |
需区分普通注释与文档注释的语法差异(/** */ vs //或/* */) |
Javadoc命令语法 |
javadoc -d [文件夹名] -author -version [文件名.java] |
参数顺序易错(如-d必须在前),忽略警告可能影响文档完整性 |
API文档结构 |
包含类描述、作者、版本、方法功能说明(如main为程序入口) |
方法注释需标注参数(@param),否则生成警告 |
文档注释内容规范 |
类注释需说明整体功能,方法注释需明确用途(如main是虚拟机执行入口) |
注解(@author、@version)需与注释内容分离 |
3.print与println区别
知识点 |
核心内容 |
重点 |
print与println的区别 |
print和println都是输出语句 |
区分print和println的输出效果 |
println输出后自带换行效果 |
println输出后会自动换到下一行 |
|
print输出后不带换行效果 |
print输出后会继续在同一行显示后续内容 |
|
JAVA操作小技巧 |
复制当前行:ctrl+d |
快捷键使用,提高编码效率 |
一次操作多行:预留空间,按住ALT键不放,鼠标往下拉 |
适用于需要同时编辑多行代码的情况 |
模块二
4.常量
知识点 |
核心内容 |
重点 |
常量定义 |
在代码运行过程中,其值不会发生改变的数据 |
区分常量与变量的关键:值是否可变 |
整数常量 |
包含所有正负整数(如 -1, 0, 100) |
无特殊易错点 |
小数常量 |
带小数点的数值(如 2.5, 2.0) |
易混淆点:2.0 是小数常量而非整数 |
字符常量 |
单引号包裹的单个内容(如 'A', ' ', '\t') |
必须且只能有一个字符: - '11' 无效(两个字符); - ' ' 有效(空格算一个字符) |
字符串常量 |
双引号包裹的任意内容(如 "Hello", "") |
空字符串 "" 是有效数据,与 null 不同 |
布尔常量 |
仅 true/false(不加引号) |
易错点:"true" 是字符串而非布尔值 |
空常量(null) |
表示数据不存在(如 null) |
与空字符串区别: - null:数据不存在; - "":数据存在但内容为空 |
5.常量使用
知识点 |
核心内容 |
重点 |
常量使用 |
常量定义与分类 |
常量在程序中的不变性 |
整数常量 |
输出整数常量示例(-1) |
整数常量的正负性 |
小数常量 |
输出小数常量示例(1.5,1.0) |
小数点后即使为零也算小数常量 |
字符常量 |
单引号中必须有且只能有一个内容 |
单引号中多个字符会报错 |
- 空格作为字符常量 |
空格也算一个字符内容 |
与多个空格区分(不算字符常量) |
- Tab键作为字符常量 |
Tab键算一个字符内容 |
与四个空格的区分 |
字符串常量 |
双引号中可以包含任意字符 |
空字符串也是合法的 |
布尔常量 |
true和false为布尔常量 |
布尔常量与字符串的区别 |
空常量 |
空常量代表数据不存在 |
空常量不能直接输出使用 |
6.变量定义与使用
知识点 |
核心内容 |
重点 |
byte类型 |
byte num1 = 100; 取值范围限制(-128~127) |
超出范围会编译报错,如byte num1 = 1000; |
short类型 |
short num2 = 1000; 可重新赋值num2 = 1001; |
变量值可动态修改,体现"变量"特性 |
int类型 |
int num3 = 10000; 默认整数类型(±21亿范围) |
直接输出变量名即可显示存储的值 |
long类型 |
long num4 = 10L; 需加后缀L/l |
必须加L/l后缀,涉及数据类型转换原理 |
float类型 |
float num5 = 2.5f; 需加后缀F/f |
必须加F/f后缀,与double区别 |
double类型 |
double num6 = 2.5; 默认小数类型 |
无需后缀,直接赋值小数 |
char类型 |
char num7 = 'a'; 单引号单字符 |
必须单引号且只能一个字符 |
boolean类型 |
boolean num8 = true; 可重新赋值num8 = num9; |
变量值传递机制(引用关系) |
String类型 |
String name = "金莲"; 双引号字符串 |
属于引用类型但定义格式类似基本类型 |
7.转义字符
知识点 |
核心内容 |
重点 |
转义字符定义 |
反斜杠在定义变量时代表转义字符,可转换字符含义 |
区分普通字符与转义字符的语法差异 |
转义字符功能 |
1. 将普通字符转为特殊含义字符; 2. 将特殊字符转为普通字符 |
反斜杠n与println的换行效果对比 |
常见转义符示例 |
- \n换行符; - \t制表符(Tab键效果) |
记忆\n与\t的具体应用场景 |
路径表示问题 |
单反斜杠引发非法转义符错误,需用\\表示真实反斜杠 |
双反斜杠的转义原理理解 |
8.标识符
知识点 |
核心内容 |
重点 |
标识符定义 |
给类、方法、变量取的名字 |
区分标识符与关键字 |
硬性规定 |
1. 可包含:英文字母、数字、$、_; 2. 不能以数字开头; 3. 不能是关键字(如static、public) |
数字开头的错误示例:int 1I |
软性建议 |
1. 类名:大驼峰式(每个单词首字母大写); 2. 方法/变量名:小驼峰式(首单词小写,后续单词首字母大写); 3. 见名知意,禁用中文 |
类名示例:Demo08; 变量名示例:publicStatic |
关键字冲突 |
避免使用Java预定义关键字(如static、public) |
组合非关键字可用(如publicStatic) |
9.强转注意事项
知识点 |
核心内容 |
重点 |
byte/short类型自动转换 |
当使用整数常量赋值且不超出范围时,JVM会自动强转 |
常量赋值无需手动强转 vs 变量参与需手动强转 |
类型提升规则 |
byte/short运算时自动提升为int型 |
b=b+1会报错需强制转换 |
char类型运算特性 |
参与运算时自动提升为int型 |
会查询ASCII/Unicode码表转换 |
ASCII码表应用 |
英文字符对应整数值查询表 |
字符'0'=48/'A'=65/'a'=97的规律 |
Unicode码表扩展 |
处理ASCII范围外的字符(如中文) |
汉字"中"=20013的编码原理 |
强制转换语法 |
(byte)(b+1)的括号使用技巧 |
整体表达式转换 vs 局部变量转换 |
模块三
10.idea常用快捷键
知识点 |
核心内容 |
重点 |
常用快捷键 |
Alt+回车:导入包及自动修正代码 |
快捷键的使用和自动修正功能 |
自动修正代码示例 |
int I = 2.5报错,Alt+回车选择cast to int修复 |
强制类型转换的自动修复 |
变量重名问题 |
在同一作用域内不能定义重名变量 |
变量命名规则和错误处理 |
无变量接收值问题 |
直接写100会报错,Alt+回车自动生成变量接收 |
变量定义和错误处理 |
导包操作 |
使用Scanner类需要导包,Alt+回车自动导包 |
类的导入和包管理 |
删除行快捷键 |
Ctrl+Y:删除光标所在行 |
快捷键的使用和代码编辑效率 |
复制当前行 |
Ctrl+D:复制当前行代码 |
快捷键的使用和代码编辑效率 |
格式化代码 |
Ctrl+Alt+L:格式化代码 |
代码格式化和可读性提升 |
单行注释 |
Ctrl+/:单行注释 |
注释的使用和代码管理 |
多行注释 |
Ctrl+Shift+/:多行注释 |
注释的使用和代码管理 |
移动当前行 |
Alt+Shift+上下箭头:移动当前行代码 |
代码编辑和重构效率 |
自动生成变量 |
先写等号右边,Alt+回车选择introduce local variable生成左边变量 |
变量定义和代码自动化 |
11.赋值运算符
知识点 |
核心内容 |
重点 |
基本赋值运算符 |
使用等号(=)进行赋值操作,先计算右边表达式再将结果赋给左边变量 |
必须区分赋值方向(右→左)与数学等号的区别 |
复合赋值运算符 |
包含+=、-=、*=、/=、%=等组合运算符 |
b += 1与b = b + 1不等价(前者自动类型转换) |
类型转换规则 |
变量参与运算时自动提升为int型,常量赋值不超范围则无需转换 |
byte/short运算必须手动强转,复合运算符例外 |
复合运算符特性 |
虚拟机对+=等操作自动处理类型转换,无需显式强转 |
实际开发中优先使用复合运算符简化代码 |
12.与或运算符
知识点 |
核心内容 |
易混淆点 |
代码验证示例 |
单与(&)运算符 |
1. 布尔型运算:有假则假; 2. 数字型运算:按位与; 3. 无短路效果(前为假仍执行后面判断) |
与双与的短路效果区别 |
int a=10,b=20; boolean r=(++a>100) & (++b>10);; 结果:a=11,b=21 |
双与(&&)运算符 |
1. 布尔型运算:有假则假; 2. 有短路效果(前为假则跳过后面判断) |
不能用于数字位运算 |
int a=10,b=20; boolean r=(++a>100) && (++b>10);; 结果:a=11,b=20 |
单或(|)运算符 |
1. 布尔型运算:有真则真; 2. 数字型运算:按位或; 3. 无短路效果(前为真仍执行后面判断) |
与双或的短路效果区别 |
int a=10,b=20; boolean r=(++a<100) | (++b>10);; 结果:a=11,b=21 |
双或(||)运算符 |
1. 布尔型运算:有真则真; 2. 有短路效果(前为真则跳过后面判断) |
不能用于数字位运算 |
int a=10,b=20; boolean r=(++a<100) || (++b>10);; 结果:a=11,b=20 |
数值区间判断 |
正确写法:i>=1 && i<=100; 错误写法:1<=i<=100(数学表达式不适用) |
Java语法与数学表达式的区别 |
int i=50; boolean inRange=(i>=1 && i<=100); |
模块四
13.Scanner类的next()方法和nextLine()方法
知识点 |
核心内容 |
重点 |
Scanner类的next()方法 |
用于录入字符串,遇到空格或回车即结束录入 |
空格会截断输入,只接收空格前的部分 |
Scanner类的nextLine()方法 |
用于录入字符串,仅遇到回车才结束录入 |
可接收包含空格的完整字符串 |
next()与nextLine()混合使用问题 |
连续使用时nextLine()会接收next()遗留的空格及后续内容 |
看似跳过输入,实际是接收了残留数据 |
数据类型匹配异常 |
nextInt()等类型方法要求输入匹配的数据类型 |
输入非整数字符会抛出InputMismatchException |
14.Random随机数
知识点 |
核心内容 |
重点 |
Random类的基本使用 |
导包→创建对象→调用方法(nextInt()) |
默认范围:int全范围随机;指定范围:nextInt(n)生成0到n-1的随机数 |
指定范围的随机数生成 |
通过数学运算调整范围(如nextInt(10)+1生成1-10) |
易错点:范围边界计算(如100-999需nextInt(900)+100) |
Random的底层机制 |
每次运行重新生成随机数,结果不可预测 |
对比:与固定种子(new Random(seed))的确定性差异 |
常见应用场景 |
抽奖、验证码、游戏数值等需随机结果的场景 |
注意:范围逻辑需严格验证(如1-100≠nextInt(100)) |
15.switch case
知识点 |
核心内容 |
重点 |
switch语句的break作用 |
break用于结束当前case语句,防止执行后续case |
忘记写break会导致case穿透 |
case穿透现象 |
当case后没有break时,程序会继续执行后续case直到遇到break或switch结束 |
穿透会执行多个case代码块 |
穿透性应用场景 |
利用穿透特性简化多条件同结果代码(如12/1/2月都输出冬季) |
需明确何时需要/不需要break |
月份季节判断案例 |
通过穿透性优化代码结构: - 冬季(12/1/2月); - 春季(3/4/5月); - 夏季(6/7/8月); - 秋季(9/10/11月) |
default处理非法输入 |
Scanner输入应用 |
配合switch实现动态输入验证: Scanner.nextInt()获取用户输入 |
输入类型需与case匹配 |
16.if与switch的区别
知识点 |
核心内容 |
重点 |
if与switch的区别 |
if从上到下逐个条件判断;switch直接跳转匹配的case |
执行流程差异(if顺序判断 vs switch精准跳转) |
if的灵活性 |
支持复杂条件逻辑(如范围判断、组合条件) |
实际开发中if使用更频繁 |
switch的效率特性 |
基于单一值快速匹配,适合离散值枚举 |
break的作用(防止case穿透) |
debug工具应用 |
通过调试观察代码执行流程 |
断点调试演示if/switch差异 |
17.do-while循环
知识点 |
核心内容 |
重点 |
do-while循环 |
先执行循环体再判断条件,至少循环一次 |
与while/for循环的区别:执行顺序差异(先循环后判断) |
语法结构 |
do {循环语句; 步进表达式;} while(比较条件); |
大括号位置、分号结尾易遗漏 |
执行流程 |
1. 初始化变量→2. 执行循环体→3. 步进表达式→4. 条件判断→重复2-4直到false |
强制首轮执行的特性 |
适用场景 |
需至少执行一次的场景(如输入校验、菜单交互) |
开发中使用频率较低 |
模块五
18.数组
知识点 |
核心内容 |
重点 |
数组长度获取 |
使用数组名.length语法(不带括号) |
length是属性不是方法,区别于nextInt()等带括号的方法调用 |
数组索引概念 |
元素在数组中的存储位置/编号(从0开始) |
最大索引=数组长度-1,索引具有唯一性 |
数组操作原理 |
所有存取查操作都需通过索引完成 |
类比旅店房间号机制(零基编号系统) |
字符串数组示例 |
String[] arr = {"迪迦奥特曼","猫和老鼠","海绵宝宝"} |
静态初始化语法与索引对应关系(0=迪迦) |
长度属性验证 |
int len = arr.length;输出元素数量 |
属性与方法语法差异(无参vs带括号) |
19.数组获取数据
知识点 |
核心内容 |
重点 |
数组元素获取方法 |
通过索引值获取元素(数组名[索引]),直接输出数组名会返回内存地址值 |
地址值 vs 元素值; 直接输出数组名返回的是地址值而非元素内容 |
数组内存机制 |
数组在内存中分配地址值(唯一标识),通过地址值可定位并操作数组 |
地址值的本质; 内存中的"身份证号",用于唯一标识数组 |
默认值规则 |
未赋值的数组元素存在默认值: - 整数:0; - 小数:0.0; - 字符:\u0000; - 布尔:false; - 引用类型:null |
动态初始化未赋值的陷阱; 系统自动赋予默认值而非"空" |
存取操作规范 |
存值需赋值(arr[0]=1),取值直接引用索引(System.out.println(arr[0])) |
操作符混淆风险; 存取语法相似但等号是关键区分点 |
20.数组扩容
知识点 |
核心内容 |
重点 |
数组扩容原理 |
通过创建新数组并复制原数组元素实现扩容,原数组引用指向新数组地址 |
数组定长特性 vs 扩容逻辑(地址值覆盖) |
内存地址机制 |
数组变量存储的是内存地址值,通过赋值操作可改变引用指向 |
地址值传递与原始数组的关系 |
代码实现步骤 |
1. 创建新数组; 2. 复制元素; 3. 地址值覆盖(oldArr = newArr) |
元素复制范围控制(避免越界) |
默认值规则 |
扩容后新增位置自动填充默认值(如int数组为0) |
未显式赋值的元素状态 |
21.内存划分
知识点 |
核心内容 |
重点 |
内存划分 |
JAVA将内存划分为五部分:栈(Stack)、堆(Heap)、方法区(Method Area)、本地方法栈(Native Method Stack)、寄存器(PC Register) |
重点掌握前三部分(栈、堆、方法区) |
栈内存(Stack) |
存储方法运行时的数据(如局部变量),方法执行时入栈,执行完毕弹栈释放内存 |
方法未及时弹栈会导致栈内存溢出 |
堆内存(Heap) |
存储对象和数组,new操作在堆中开辟空间并分配地址值,数据有默认值(如int=0、boolean=false) |
地址值的作用(通过变量引用堆中对象) |
方法区(Method Area) |
代码预备区,存储类信息和方法信息(如.class文件内容) |
与栈/堆的协作关系(代码加载→方法区→运行时分配) |
本地方法栈 |
运行Native方法(如C语言编写的底层功能,扩展JAVA能力) |
与硬件交互的场景(如IO流读写硬盘) |
内存协作流程 |
示例: int[] arr = new int[3]; 1. .class加载到方法区; 2. main方法入栈运行; 3. new在堆中开辟数组空间(含默认值); 4. 变量arr保存堆内存地址 |
地址指向的实际意义(变量通过地址操作堆内对象) |
22.二维数组
知识点 |
核心内容 |
重点 |
二维数组定义 |
使用两个中括号表示二维数组,本质是"数组套数组" |
动态初始化与静态初始化的语法区别 |
动态初始化语法 |
数据类型[][] 数组名 = new 数据类型[m][n]; 三种变体:中括号前置/后置/分开放置 |
m代表二维数组长度(包含的一维数组数量); n代表每个一维数组的长度 |
特殊动态初始化 |
new 数据类型[m][]形式表示一维数组未被创建; 未创建的一维数组默认值为null |
与带n声明的区别:后者已创建但元素为默认值 |
静态初始化 |
直接赋值:数据类型[][] 数组名 = {{元素1,元素2},{...}}; 支持简化写法省略new关键字 |
各一维数组长度可不一致; 与动态初始化固定长度的区别 |
内存结构示例 |
图示说明new int[2][3]和new int[2][]的内存分配差异 |
null与默认值的内存状态区别 |
典型应用场景 |
不规则二维数组案例: {{"孙悟空","唐僧"},{"刘备","关羽","张飞"}} |
静态初始化更适合非对称数据结构 |
模块六
23.方法定义
知识点 |
核心内容 |
重点 |
方法定义通用格式 |
修饰符 + 返回值类型 + 方法名 + 参数 + 方法体 + return结果 |
void与return的冲突(void方法不可return具体值) |
修饰符作用 |
public static固定搭配(公共访问权限 + 静态方法) |
面向对象阶段会详细解释 |
返回值类型 |
由return结果的数据类型决定(如int/double/String) |
无返回值时需用void |
方法命名规范 |
小驼峰命名法(如getSum) |
需见名知意 |
参数定义 |
数据类型 + 变量名(多个参数用逗号隔开) |
调用时赋值,定义时不需初始化 |
方法体与return |
方法体为具体实现代码;return返回结果(仅非void方法可用) |
方法体操作参数生成返回值(类比“牛消化饲料产奶”) |
IDE分割线设置 |
勾选Show Method显示方法间分割线(解决代码混淆问题) |
路径:File → Settings → Editor → General → Appearance |
24.无参有返回值方法
知识点 |
核心内容 |
重点 |
无参有返回值方法的定义 |
public static+返回值类型+方法名() {} |
返回值类型不能写void,方法体需包含return语句 |
返回值的处理 |
方法体内通过return语句返回结果 |
返回值类型需与方法体内返回的数据类型一致 |
方法调用的两种方式 |
直接调用和赋值调用 |
直接调用将结果直接输出,赋值调用将结果赋值给变量 |
打印调用(直接调用) |
调用方法后,将结果直接放入输出语句中 |
适用于不需要再次使用结果的情况 |
赋值调用 |
调用方法后,将结果赋值给一个变量 |
推荐方式,便于后续使用结果 |
执行流程 |
调用方法 -> 执行方法体 -> 返回结果 -> 接收结果 |
理解方法调用的整个过程,特别是返回值的接收 |
示例:整数相加方法 |
public static int sum(int a, int b) { return a+b; } |
方法的定义、调用和返回值处理 |
25.方法_参数和返回值使用时机
知识点 |
核心内容 |
重点 |
参数的使用时机 |
当想将方法A的数据传递到方法B时,定义方法B需要带参数 |
参数传递的机制和目的 |
返回值的使用时机 |
调用方法A时,想要方法A的结果去参与其他的操作,方法A需要返回结果 |
返回值类型与接收 |
三层架构思想 |
Controller层(接收请求回响应)、Service层(业务逻辑)、DAO层(持久层) |
各层职责与协作方式 |
参数在三层架构中的应用 |
Ctrl层接收请求参数,通过参数传递到Service层,Service层再通过参数传递到DAO层 |
参数在各层之间的传递与接收 |
返回值在三层架构中的应用 |
DAO层查询结果需要返回给Service层,Service层处理结果需要返回给Ctrl层 |
返回值的传递与接收,以及根据返回值做不同的响应 |
三层架构的框架对应 |
Ctrl层对应Spring MVC,Service层对应Spring,DAO层对应MyBatis |
SSM框架的组成与对应层次 |
26.方法注意事项
知识点 |
核心内容 |
重点 |
方法注意事项 |
方法不调用不执行;执行顺序仅与调用顺序相关;方法间不可嵌套 |
void与return的共存规则 |
void与return的关系 |
void表示无返回值,不可与return 结果共存,但可与return(无数据)共存 |
return 结果会先返回数据再结束方法;return仅结束方法 |
方法中的return限制 |
一个方法不能连续写多个return(语法错误);if-else分支中的return需覆盖所有逻辑路径 |
多返回值需用数组封装;未覆盖分支的return会报错 |
方法调用前提 |
调用方法前需确认方法已定义,否则报错 |
常见错误:未定义直接调用 |
27.方法调用技巧
知识点 |
核心内容 |
重点 |
方法定义与调用 |
先定义后调用,避免报错 |
定义顺序错误导致报错 |
返回值处理 |
无返回值方法在方法内输出;有返回值方法需用变量接收后输出 |
返回值类型与接收变量不匹配 |
方法调用方式 |
直接调用(无返回值)、打印调用(不推荐)、赋值调用(推荐) |
混淆调用方式适用场景 |
28.方法重载
知识点 |
核心内容 |
重点 |
方法重载的判断标准 |
方法名相同且参数列表不同(类型/顺序/数量) |
与返回值类型、参数名称无关 |
重载方法调用冲突 |
当参数类型存在隐式转换时可能导致调用歧义(如int和double) |
sum(10, 2.5)可能同时匹配多个重载 |
典型重载场景 |
相同功能不同实现细节(如集合的add()方法) |
位置添加 vs 末尾添加属于合法重载 |
非法重载示例 |
仅修改参数名(int a vs int x)或返回值类型 |
编译器报错:"method is already defined" |
合法重载变体 |
无参/有参、类型顺序不同((int,double) vs (double,int)) |
方法签名实质不同即可 |
方法签名唯一性 |
严格区分大小写(Open()与open()不算重载) |
视为完全独立的方法 |
模块七
29.面向对象思想
知识点 |
核心内容 |
重点 |
面向对象思想 |
核心编程思想,强调“调用他人功能”而非亲力亲为(如洗衣机洗衣服、外卖点餐等类比) |
与面向过程的区别(C语言 vs Java); 关键判断标准:是否调用其他类的成员 |
类与对象 |
类(Class)是模板,对象是实例(如Scanner/Random的new操作) |
new对象后通过.调用方法; 特殊场景:静态方法(static)可直接类名调用(如Arrays.toString()) |
匿名对象 |
一次性使用的对象(未赋变量名) |
内存效率 vs 代码可读性权衡 |
对象内存解析 |
堆栈内存分配机制(对象在堆,引用在栈) |
易混淆点:基本类型 vs 引用类型的存储差异 |
成员变量与局部变量 |
作用域与生命周期对比(类内全局 vs 方法内临时) |
默认值差异:成员变量自动初始化,局部变量需手动赋值 |
面向对象应用场景 |
调用他人功能时使用(如Scanner.nextInt()、Random.nextInt()) |
典型误区:自身类内方法调用不属面向对象 |
代码简化案例 |
Arrays.toString(arr) vs 手动遍历拼接字符串 |
效率对比:面向对象减少重复代码量 |
30.对象的使用
知识点 |
核心内容 |
重点 |
类与对象概念 |
类是一类事物的抽象表示形式,对象是类的具体实例 |
抽象vs具体体现的辩证关系 |
对象创建三步法 |
1. 导包 2. 创建对象 3. 调用成员 |
同包下免导包规则与java.lang包特殊性 |
对象成员调用 |
对象名.成员变量 / 对象名.方法() |
方法调用的四种组合形式(有参无参/有返回值无返回值) |
默认值机制 |
未赋值的成员变量自动初始化(如String=null, int=0) |
默认值陷阱在业务逻辑中的影响 |
面向对象基础语法 |
类名 对象名 = new 类名()标准创建格式 |
对象名命名规范与内存指向原理 |
包访问规则 |
同包类直接互访 vs 跨包需导包 |
import语句的精确导入与通配符导入区别 |
31.匿名对象
知识点 |
核心内容 |
重点 |
匿名对象的使用 |
匿名对象即没有变量名直接使用的对象,通过new关键字直接创建并调用方法或访问成员变量 |
匿名对象适用于一次性调用方法,不适用于需要多次访问或修改对象状态的场景 |
原始方式与匿名对象的对比 |
原始方式:使用变量接收对象,可以多次访问和修改对象状态;匿名对象方式:直接创建并使用对象,无法后续访问或修改 |
易混淆点:匿名对象无法保存状态,每次使用都会创建新的对象实例 |
匿名对象的适用场景 |
适用于只需要调用对象方法,不需要保存对象状态的场景,如调用工具类的方法 |
误用匿名对象进行赋值操作,会导致无法后续访问或修改该值 |
原始方式的优势 |
可以保存对象状态,方便后续访问和修改,适用于需要多次使用对象的场景 |
|
堆栈内存分析 |
原始方式中,对象存储在堆内存中,变量名保存在栈内存中,通过变量名可以访问堆内存中的对象;匿名对象只存在于堆内存中,无法通过变量名访问 |
理解堆栈内存模型对于掌握对象存储和访问机制至关重要 |
32.两个对象指向同一片空间
知识点 |
核心内容 |
重点 |
对象内存分配原理 |
两个对象变量指向同一内存空间时的数据共享机制 |
地址值传递导致的对象关联性 |
引用类型变量赋值 |
通过Phone p2 = p1实现对象引用传递 |
直接赋值与new创建的本质区别 |
堆栈内存交互 |
栈内存存储引用地址,堆内存存储实际对象数据 |
方法区存储类模板的class对象 |
对象属性修改影响 |
通过任一引用修改属性会同步影响所有关联对象 |
多引用操作同一对象的副作用 |
内存图绘制方法 |
三区域划分(栈/堆/方法区)与地址指向关系 |
数组与对象内存模型的相似性 |
33.成员变量和局部变量
知识点 |
核心内容 |
重点 |
成员变量 vs 局部变量 |
定义位置不同:成员变量在类中方法外,局部变量在方法内或参数位置 |
初始化值差异:成员变量有默认值,局部变量需手动赋值 |
作用范围不同:成员变量作用于整个类,局部变量仅限所在方法 |
内存位置:成员变量在堆中,局部变量在栈中(非重点) |
|
生命周期不同:成员变量随对象创建/销毁,局部变量随方法调用/结束(非重点) |
||
成员变量默认值规则 |
未手动赋值时,成员变量自动赋予默认值(如String为null) |
易错点:局部变量未赋值直接使用会报错 |
作用域验证示例 |
Person类中name(成员变量)可在所有方法调用,而方法内变量(如i)仅限本方法 |
混淆点:误将局部变量跨方法调用 |
模块八
34.封装 private
知识点 |
核心内容 |
重点 |
封装的概念 |
将代码片段放入方法中隐藏实现细节,对外提供公共接口(方法名)调用 |
区分“代码封装”与“属性封装”的异同 |
private关键字 |
私有化修饰成员变量/方法,限制仅本类访问,强制通过公共接口间接操作 |
不合理赋值问题(如年龄赋负值)的解决方案 |
封装的实际应用 |
1. 方法封装代码逻辑; 2. private封装属性+公共setter/getter控制赋值逻辑 |
setter方法中加入有效性校验(如if(age>0)) |
封装的优势 |
1. 隐藏实现细节; 2. 增强数据安全性; 3. 降低耦合度 |
对比public与private的访问权限差异 |
案例演示 |
1. 数组打印方法封装; 2. Person类属性私有化+setAge校验 |
易错点:忘记提供公共访问接口导致数据无法操作 |
35.get set方法
知识点 |
核心内容 |
重点 |
封装思想 |
使用private隐藏属性细节,通过get/set方法提供公共访问接口 |
私有化属性后仍需通过方法控制赋值有效性(如setAge中校验负值) |
get/set方法作用 |
set用于属性赋值(可加入逻辑校验),get用于属性取值 |
方法内可直接访问本类私有成员(与外部调用区别) |
封装实现流程 |
1. 属性私有化 → 2. 编写带校验的set方法 → 3. 编写get方法 → 4. 外部通过方法间接访问 |
校验逻辑需覆盖边界值(如年龄>150) |
封装优势 |
防止不合理赋值(如age=-18)、隐藏实现细节、统一访问入口 |
private限制的是外部直接访问而非本类内部访问 |
36.this关键字
知识点 |
核心内容 |
重点 |
this关键字基本使用 |
通过this区分重名成员变量与局部变量,遵循就近原则(默认访问局部变量) |
成员变量与局部变量重名时的访问优先级 |
this代表当前对象 |
this指向调用该方法的对象,通过输出对象地址值验证(person与person2调用时this指向不同) |
动态绑定机制:this具体指向由调用对象决定 |
标准get/set方法改造 |
形参与成员变量同名时,用this.变量名明确赋值目标(如this.name = name) |
未用this会导致局部变量自赋值(age=age无效) |
代码示例分析 |
speak()方法中this.name输出成员变量,name输出局部变量(传参"刘彦昌") |
输出结果差异:this.name为"沉香",name为"刘彦昌" |
对象调用验证 |
person.speak()与person2.speak()中this分别指向不同对象地址 |
通过分割线对比两对象地址值及this指向 |
37.构造方法
知识点 |
核心内容 |
重点 |
构造方法定义 |
方法名与类名一致,用于初始化对象,无返回值(连void也不写) |
易混淆:new 类名()实际调用的是构造方法,而非创建类本身 |
构造方法分类 |
无参构造(默认存在,虚拟机自动提供)、有参构造(为属性赋值)、满参构造(为所有属性赋值) |
重点:默认无参构造在类中未显式定义时仍存在 |
无参构造特点 |
格式:public 类名(){};作用:仅用于new对象 |
易错点:手动定义后,默认无参构造失效 |
构造方法调用 |
通过new关键字隐式调用(无需对象.操作) |
示例:Person p = new Person();直接触发无参构造执行 |
IDEA快捷操作 |
自动生成get/set方法和构造方法(如Alt+Insert) |
知识点 |
核心内容 |
考试重点/易混淆点 |
有参构造 |
定义格式:public 类名(参数列表){为属性赋值} |
与无参构造的区别、如何为属性赋值 |
作用:创建对象的同时为属性赋值 |
有参构造与set方法的区别 |
|
写法示例:public Person(String name, int age){this.name=name; this.age=age;} |
构造方法重载(参数列表不同) |
|
注意:手写有参构造后,无参构造需手动添加 |
虚拟机默认提供无参构造,手写有参后不再自动提供 |
|
属性赋值 |
通过有参构造、set方法为属性赋值 |
私有属性如何通过有参构造和set方法赋值 |
方法调用 |
按住Ctrl键,鼠标点击方法名可快速定位到方法定义 |
如何快速找到调用的方法 |
get/set方法 |
get方法用于获取属性值,set方法用于设置属性值 |
get/set方法的作用、使用场景 |
构造方法重载 |
多个构造方法,参数列表不同 |
构造方法重载的意义、如何实现 |
38.JavaBean
知识点 |
核心内容 |
重点 |
Java Bean定义 |
符合特定规范的Java类: 1. 公共类(public class); 2. 提供无参/有参构造方法; 3. 成员变量私有化; 4. 提供get/set方法 |
易混淆点: - 非私有属性也可提供get/set,但无实际意义 |
分层架构与分包 |
开发时按功能分包: - controller(表现层); - service(业务层); - dao(持久层); - pojo(存放Java Bean); - util(工具类) |
重点: - 包名规范(公司域名倒写); - 类的职责隔离 |
Java Bean使用场景 |
1. 通过set方法或有参构造赋值; 2. 通过get方法取值; 3. 实体类统一存放于pojo包 |
易错点: - 无参构造方法体通常为空 |
39.javabean参与添加功能
知识点 |
核心内容 |
易混淆点/关键细节 |
参与环节 |
三层架构 |
表现层(Controller)、业务层(Service)、持久层(DAO)的分工 |
表现层仅处理请求/响应,业务逻辑应集中在Service层 |
整体框架设计 |
注册功能流程 |
1. 页面输入 → 2. Controller获取参数 → 3. 封装为JavaBean → 4. 逐层传递至DAO → 5. 数据库操作 |
参数封装必要性(避免多参数传递混乱) |
功能实现核心链路 |
JavaBean作用 |
数据打包(如User对象含ID、用户名、密码)、跨层传输、属性提取(get/set方法) |
与DTO/VO的区别(本例未涉及分层模型) |
数据封装与传递 |
DAO层逻辑 |
1. 用户名查重 → 2. 无重复则插入数据 |
查询与插入的原子性 |
数据库交互 |
响应控制 |
Controller根据Service返回结果(如1/0)动态响应页面 |
状态码设计(可扩展为枚举/常量) |
结果反馈 |
模块九
40.static关键字
知识点 |
核心内容 |
重点 |
static关键字 |
用于修饰成员变量和方法,使成员属于类而非对象,实现数据共享 |
静态成员与非静态成员的内存加载顺序(静态优先) |
静态成员特点 |
1. 类加载时即存在; 2. 通过类名直接调用; 3. 所有对象共享同一静态成员 |
区分类名.静态成员与对象.非静态成员的调用方式 |
应用场景 |
解决多对象共享属性问题(如班级换教室只需修改一次静态变量) |
静态方法中不可直接调用非静态成员(需先实例化对象) |
内存机制 |
静态成员存储在方法区,非静态成员存储在堆内存对象中 |
易混淆:静态成员生命周期与类相同,非静态成员与对象绑定 |
代码示例 |
static String classroom = "111";; 修改时:Student.classroom = "222"; |
需注意静态变量初始化的线程安全问题 |
41.static内存说明
知识点 |
核心内容 |
重点 |
static成员的内存存储位置 |
静态成员存储在静态域中,静态域在JDK 6时位于方法区(永久代),JDK 7开始移至堆内存 |
方法区 vs. 堆内存:JDK 7后静态域迁移至堆,目的是提高内存回收效率 |
方法区的演变 |
JDK 6称“永久代”,JDK 8改为“元空间”,但均为方法区的具体实现 |
永久代、元空间与方法区的关系:需明确三者是同一逻辑区域的不同实现 |
静态域迁移原因 |
堆内存回收效率高,方法区回收效率低;迁移后可及时释放静态成员占用的内存 |
为什么静态域不留在方法区?:避免内存长期占用,优化运行性能 |
静态成员共享机制 |
静态成员随类加载而加载,被该类的所有对象共享;不属于对象成员,仅属于类 |
静态成员访问方式:直接通过类名调用(如Student.classroom),无需实例化对象 |
内存模型示例(Student类) |
classroom(静态)存储在堆的静态区,name(实例)存储在对象堆内存;新建对象共享静态成员 |
对象与静态区的关系:对象通过内存地址共享静态成员,但静态成员生命周期独立于对象 |
42.静态成员访问特点
知识点 |
核心内容 |
重点 |
静态方法访问非静态成员 |
静态方法中不能直接访问非静态成员,需通过new对象调用 |
先出生的静态成员无法直接访问后出生的非静态成员(类比秦始皇不知康熙存在) |
非静态方法访问静态成员 |
非静态方法中能直接访问静态成员(同类可直接调用/类名调用,不同类需类名调用) |
反编译证明即使通过对象调用静态方法,底层仍是类名调用 |
静态方法访问静态成员 |
静态方法中能直接访问静态成员(同类可直接调用,不同类需类名调用) |
同类访问时存在两种调用方式(直接调用/类名调用) |
非静态方法访问非静态成员 |
非静态方法中能直接访问非静态成员(同类直接调用,不同类需new对象调用) |
同类访问时new对象调用非必要但可行 |
通用访问规则总结 |
非静态成员始终通过new对象调用;静态成员始终推荐类名调用 |
静态成员生命周期早于非静态成员(类加载vs对象实例化) |
43.静态成员的使用场景
知识点 |
核心内容 |
重点 |
静态成员的使用场景 |
静态成员通过类名直接调用,无需实例化,适用于工具类等场景 |
静态成员与实例成员的区别(内存加载时机) |
静态成员的局限性 |
所有静态成员会在类加载时占用内存,滥用会导致内存浪费 |
需权衡“便利性”与“资源占用” |
工具类设计规范 |
1. 成员全静态化; 2. 构造方法私有化(禁止实例化); 3. 功能需高频复用(如数组求最大值) |
工具类与普通类的设计差异 |
代码复用案例 |
抽取ArrayUtils.getMax()方法,避免重复编写数组遍历逻辑 |
工具类方法的通用性设计(参数/返回值) |
44.可变参数
知识点 |
核心内容 |
注意事项 |
可变参数定义 |
使用数据类型...变量名语法定义(必须三个点) |
必须三个点,两个或四个点都不行 |
可变参数本质 |
底层实现是数组(可通过反编译验证) |
可使用数组遍历方式操作可变参数 |
参数位置规则 |
可变参数必须放在参数列表最后 |
报错提示:varargs parameter must be the last |
多参数共存 |
可与普通参数共存(如int i, int... arr) |
普通参数需在前,顺序不可颠倒 |
方法调用方式 |
可传入任意数量同类型参数(自动转为数组) |
类型必须匹配定义的数据类型 |
45.递归
知识点 |
核心内容 |
重点 |
递归的定义 |
方法内部调用自身的编程技巧 |
与循环的区别(出口条件的必要性) |
递归的经典案例 |
"从前有座山"的无限循环故事 |
无出口的递归导致栈溢出错误 |
递归的分类 |
直接递归(方法A调A)和间接递归(方法A→B→C→A循环调用) |
间接递归的代码实现逻辑 |
递归的注意事项 |
必须设置终止条件(出口),且递归次数不宜过多 |
栈内存溢出的原理(StackOverflowError) |
递归的代码演示 |
method()无限调用自身导致崩溃 |
实际开发中需通过条件判断控制递归深度 |
46.斐波那契数列
知识点 |
核心内容 |
重点 |
斐波那契数列定义 |
数列中每个数字是前两个数字之和(从1,1开始) |
起始项定义(通常为F(1)=1, F(2)=1) |
兔子繁殖模型 |
1.新生兔1个月成熟; 2.成熟后每月生1对; 3.无死亡假设 |
第二个月不生兔的时间延迟特性 |
递归算法实现 |
method(n) = method(n-1) + method(n-2) |
终止条件必须包含n=1和n=2的情况 |
数列计算示例 |
月份:1→1对, 2→1对, 3→2对, 4→3对, 5→5对, 6→8对 |
第6个月结果8对的推导过程 |
递归调用过程 |
方法自调用时的参数传递机制(月份递减) |
递归树展开时的重复计算问题 |
47.数组反转
知识点 |
核心内容 |
重点 |
数组翻转算法 |
中心思想是数组对称索引位置上的元素互换,通过中间变量实现元素位置交换 |
确定交换终止条件(min >= max)和索引移动规则(min++/max--) |
索引对称原理 |
奇数数组中间元素自对称,偶数数组全部成对交换(图示[1,2,3,4,5,6,7]与[7,6,5,4,3,2,1]索引对应关系) |
奇偶数组的不同处理逻辑 |
元素交换技术 |
使用临时变量temp的三步交换法: 1. temp = arr[min]; 2. arr[min] = arr[max]; 3. arr[max] = temp |
类比水杯交换的具象化理解 |
循环控制逻辑 |
for(int min=0,max=arr.length-1; min<max; min++,max--) 复合循环条件写法 |
多语句初始化/迭代的语法特性 |
边界条件处理 |
循环终止条件min < max同时覆盖奇偶两种情况 |
避免偶数数组重复交换 |
48.冒泡排序
知识点 |
核心内容 |
重点 |
冒泡排序定义 |
数组排序方法,通过相邻元素比较和交换实现排序 |
默认升序排序,需理解“相邻元素”指 arr[i] 和 arr[i+1] |
排序过程 |
1. 每轮将最大值“冒泡”到末尾; 2. 比较轮数=数组长度-1,每轮比较次数递减 |
易错点:忽略每轮减少一次比较(已排序部分无需重复比较) |
代码实现关键 |
1. 双重循环(外层控制轮数,内层控制比较次数); 2. 相邻元素交换条件 arr[i] > arr[i+1] |
笔试高频:需默写代码框架及边界条件(如 i < arr.length-1) |
性能特点 |
时间复杂度 O(n²),空间复杂度 O(1) |
对比其他排序:效率低但实现简单,适合小规模数据 |
实例演示 |
数组 [5,4,3,2,1] 的完整排序步骤(4轮比较,每轮次数递减) |
重点观察:最大值如何逐步移动到末尾 |
49.二分查找
知识点 |
核心内容 |
重点 |
二分查找原理 |
通过不断折半缩小查找范围,提升查询效率 |
必须保证数组有序(升序/降序) |
中间索引计算 |
mid = (min + max) // 2,动态调整min/max |
初始min=0,max=长度-1,非固定长度/2 |
查找流程 |
1. 比较目标值与mid元素; 2. 大于则min=mid+1; 3. 小于则max=mid-1; 4. 等于则命中 |
终止条件:min > max时未找到 |
效率对比 |
原始遍历:O(n); 二分查找:O(log n) |
数据量越大优势越显著(例:100数据仅需7次比较) |
边界案例 |
目标值在首尾/不存在时索引移动逻辑 |
min/max更新需严格±1,避免死循环 |
50.对象数组
知识点 |
核心内容 |
重点 |
对象数组定义 |
Person[]数组存储Person对象,数组定义语法与基本类型数组类似 |
数组元素类型与对象类型的匹配关系 |
对象数组初始化 |
创建三个Person对象并存入数组,通过索引赋值 |
数组存储的是对象引用(地址值)而非对象本身 |
数组遍历与属性访问 |
使用for循环遍历数组,通过getter方法获取对象属性 |
遍历得到的是对象引用,需通过引用访问成员方法 |
内存模型解析 |
堆内存中数组元素存储对象引用示意图 |
引用传递与值传递的本质区别 |
类型系统应用 |
接收数组元素必须使用Person类型变量 |
编译期类型检查机制 |
51.对象数组应用
知识点 |
核心内容 |
重点 |
对象数组创建 |
创建Student类数组并初始化三个学生对象 Student[] students = new Student[3] |
匿名对象初始化方式 |
类定义规范 |
定义Student类包含私有属性(name/score)和标准方法(构造器/getter) |
无参/有参构造器同时存在的必要性 |
冒泡排序算法 |
通过嵌套循环实现对象数组排序 |
比较成绩但交换整个对象 |
对象属性访问 |
通过getter方法获取私有属性进行比较 |
直接访问私有属性会导致编译错误 |
数组遍历输出 |
排序后遍历数组输出学生信息 |
注意数组越界问题 |
52.基本类型做参数传递
知识点 |
核心内容 |
重点 |
基本数据类型与引用数据类型的区分 |
基本数据类型包括四类八种(byte、short、int、long、float、double、char、boolean),其余均为引用数据类型 |
如何快速区分:只需记住基本数据类型的范围,其余均为引用类型 |
方法参数传递(基本数据类型) |
基本数据类型作为方法参数传递时,传递的是值而非变量本身,方法内部的修改不影响原始变量 |
易混淆点:误认为方法内部修改会影响原变量值 |
方法调用与栈内存机制 |
方法执行时压栈,运行完毕后弹栈,局部变量仅作用于当前方法栈帧 |
关键理解:方法栈的独立性导致变量作用域隔离 |
53.引用类型作参数传递
知识点 |
核心内容 |
重点 |
引用数据类型作为方法参数传递 |
引用数据类型(如数组)作为参数传递时,传递的是地址值,而非值本身。 |
区分基本数据类型和引用数据类型的参数传递方式;理解为何引用数据类型的修改会影响到原数据。 |
数组在内存中的存储 |
数组在堆内存中存储,变量保存的是数组的地址值。 |
数组的内存分配和地址值的概念;数组如何通过地址值进行访问和修改。 |
方法调用与栈的压栈弹栈 |
方法调用时,会在栈中压栈运行;方法执行完毕后,会弹栈返回。 |
方法调用的栈机制;压栈与弹栈对变量值的影响。 |
方法间参数传递的影响 |
引用数据类型作为参数传递时,方法间的修改会相互影响。 |
引用传递导致的修改共享问题;如何理解并避免不必要的修改。 |
基本数据类型与引用数据类型的区别 |
基本数据类型传递的是值,引用数据类型传递的是地址值。 |
两者在参数传递、内存存储和修改影响上的区别。 |
54.命令行参数
知识点 |
核心内容 |
重点 |
命令行参数 |
指main方法中的String[] args参数,通过命令行或IDE配置传递实参 |
参数传递格式(空格分隔)、IDE配置入口位置 |
参数传递方式 |
1. 命令行运行:java 类名 参数1 参数2; 2. IDEA配置:Run → Edit Configurations → Program Arguments |
参数与类名需空格分隔,参数按顺序对应数组元素 |
实际应用场景 |
临时测试方法功能(如method(String s1, String s2)),避免启动完整项目流程 |
与直接调用方法的区别(灵活性 vs 便捷性) |
IDE操作演示 |
1. 创建类并编写main方法; 2. 通过Edit Configurations设置参数(如哈哈 嘿嘿); 3. 运行后遍历args数组输出结果 |
配置路径易忽略(需通过类名旁箭头进入) |
55.快速生成方法
知识点 |
核心内容 |
重点 |
方法定义与调用顺序 |
初学者需先定义方法再调用,否则报错;熟练者可先调用后定义(通过IDE补全) |
Alt+Enter快速生成方法(自动补全参数/返回值) |
IDE智能补全功能 |
使用Alt+Enter自动生成方法: - 无参无返回值(默认private修饰); - 有参无返回值(自动匹配参数类型); - 有返回值(自动推断类型) |
修饰符需手动调整 |
代码抽取为方法 |
选中代码块后按Ctrl+Alt+M快速抽取: - 自动识别依赖变量(如数组参数); - 支持修改方法名/修饰符; - 智能提示返回值需求 |
未选中变量时自动补全参数 |
IDE操作效率技巧 |
- 通过快捷键生成代码结构; - 抽取重复逻辑为独立方法 |
需熟悉Alt+Enter与Ctrl+Alt+M组合键 |
56.debug调试
知识点 |
核心内容 |
重点 |
Debug调试概述 |
调试代码的手段,用于监测变量变化和定位错误 |
理解断点作用与调试模式启动方式 |
断点设置 |
在代码行左侧点击添加红色圆点(断点),右键选择Debug启动调试 |
断点可多位置设置,点击消失的特性易忽略 |
调试面板功能 |
- 下一步(逐行执行); - 进入方法(跳转至被调用方法内部); - 跳出方法(返回调用处); - 放行(执行当前请求代码但不退出调试); - 结束调试(完全退出) |
放行 vs 结束调试的功能差异(是否保留调试模式) |
变量监控 |
调试过程中实时显示变量值变化(如数组索引赋值过程) |
通过变量面板观察I=3时的数组越界问题 |
调试应用场景 |
示例:购物车功能调试(addCart方法逐行检查变量) |
结合循环调用演示放行按钮的多次触发特性 |