Java学习笔记
📚 目录结构
1. Java简介
1.1 什么是Java?
Java是一门编程语言,是一组有序的指令集,用于驱动计算机工作。
编程语言发展史:
- 第一代语言:机器语言(0,1)
- 第二代语言:汇编语言(mov、add、寄存器)
- 第三代语言:高级语言
- 面向过程:C(指针)、C++(游戏引擎)
- 面向对象:Java、C#、Objective-C、JavaScript
- 第四代语言:SQL
1.2 Java能做什么?
- 企业级开发:OA、ERP、教务系统、电商平台(淘宝)
- 移动互联网:App、车联网、互联网电视、智能家居
- 大数据:数据挖掘与分析
1.3 Java前景如何?
- 平台开发:后端服务、微服务架构
- 移动互联网:Android应用开发
- 物联网时代:云计算、大数据、物联网设备
1.4 Java特点
| 特点 | 说明 |
|---|---|
| 跨平台 | Java代码跨平台,JVM不跨平台 |
| 多线程 | 单位时间内完成多个任务 |
| 安全性 | 相对其他语言更安全 |
| 面向对象 | 支持封装、继承、多态等OOP特性 |
1.5 Java核心概念
JDK、JRE、JVM关系图:
JDK (Java开发工具包)
├── JRE (Java运行环境)
│ ├── JVM (Java虚拟机)
│ └── 核心类库
└── 开发工具(javac、java等)
详细说明:
JDK (Java Development Kit):Java开发工具包
- 包含:可执行文件 + JRE + 源代码
JRE (Java Runtime Environment):Java运行环境
- 包含:JAR包(工具代码)+ JVM
JVM (Java Virtual Machine):Java虚拟机
- 作用:模拟一台计算机,运行Java程序
Java技术体系:
| 技术平台 | 说明 |
|---|---|
| JavaSE | Java标准版,基础语法 |
| JavaEE | Java企业版,用于企业级开发(Web应用) |
| JavaME | Java微型版,用于移动设备开发 |
1.6 JDK目录结构
jdk/
├── bin/ 开发过程中依赖的工具包(命令)
├── db/ 数据方面的案例
├── demo/ Java新功能的案例
├── include/ Java底层是C语言
├── jre/ 运行环境
├── lib/ 库文件
└── src.zip Java源代码
2. 开发环境搭建
2.1 JDK安装步骤
- 下载JDK安装包(推荐Oracle JDK)
- 按提示一步步安装即可
- 配置环境变量
2.2 环境变量配置
Windows系统配置步骤:
- 右击”计算机” → “高级系统设置”
- 在”系统变量”中找到
Path变量 - 在变量值的最前面输入JDK的bin目录路径,并以
;结尾
# 示例:C:\Program Files\Java\jdk1.8.0\bin;
- 点击”确定”保存
验证安装:
# 打开命令行窗口,输入以下命令
java -version
javac -version
2.3 IDE开发工具
MyEclipse/Eclipse安装与配置:
- 下载并安装IDE
- 配置JRE路径:
Window → Preferences → Java → Installed JREs - 配置工作空间编码:
Window → Preferences → General → Workspace → Text file encoding
常用操作:
| 操作 | 菜单路径 |
|---|---|
| 新建项目 | File → New → Java Project |
| 新建包 | File → New → Package |
| 新建类 | File → New → Class |
| 更改字体 | Window → Preferences → General → Appearance → Colors and Fonts |
命名规范:
- 项目名:英文小写
- 包名:
com.xxx格式 - 类名:驼峰命名法(如:
HelloWorld)
3. 基础语法
3.1 数据类型
Java数据类型分为两大类:
数据类型
├── 基本数据类型
│ ├── 数值型
│ │ ├── 整数型:byte、short、int、long
│ │ └── 浮点型:float、double
│ ├── 字符型:char
│ └── 布尔型:boolean
└── 引用类型
├── 类:String、Scanner、Random等
├── 接口
└── 数组
基本数据类型详细表:
| 类型 | 取值范围 | 默认值 | 占用字节 | 说明 |
|---|---|---|---|---|
boolean | true|false | false | 1位 | 布尔类型 |
byte | -2⁷ ~ 2⁷-1 (-128 ~ 127) | 0 | 1字节 | 字节型 |
short | -2¹⁵ ~ 2¹⁵-1 (-32768 ~ 32767) | 0 | 2字节 | 短整型 |
char | 0~65535 (Unicode字符集) | \u0000 | 2字节 | 字符型 |
int | -2³¹ ~ 2³¹-1 | 0 | 4字节 | 整型(默认) |
long | -2⁶³ ~ 2⁶³-1 | 0L | 8字节 | 长整型 |
float | ±3.4e38 (7位有效数字) | 0.0f | 4字节 | 单精度浮点 |
double | ±1.8e308 (15位有效数字) | 0.0d | 8字节 | 双精度浮点(默认) |
重要提示:
整数的默认类型是int类型
long k; k = 123123213L; // 必须加L或l小数的默认类型是double类型
float f; f = 1.3f; // 必须加f或F
3.2 变量
概念: 用来指代一定范围的值的一个代词
定义语法:
数据类型 变量名; // int a;
赋值语法:
变量名 = 值; // a = 10; 注意:'='前后各空一格
变量命名规范:
- 只能包含字母、数字、下划线和美元符号
- 不能以数字开头
- 不能使用Java关键字
- 见名知意
3.3 注释
三种注释方式:
| 注释类型 | 语法 | 用途 |
|---|---|---|
| 单行注释 | //注释内容 | 解释某一行代码 |
| 多行注释 | /* 注释内容 */ | 解释某一段代码 |
| 文档注释 | /** 注释内容 */ | 解释某个方法或类 |
文档注释示例:
/**
* VarExample主要用来演示变量定义及变量的赋值
*
* @author Andy
* @since 2016-4-25
*/
public class VarExample {
/**
* main函数是用来给操作系统调用的函数,所以写法固定
*
* @param args 在执行java命令时可以传递参数
* @return 没有返回值
*/
public static void main(String[] args) {
// 代码内容
}
}
3.4 类型转换
数据类型范围从小到大:
char → byte → short → int → long → float → double
两种类型转换方式:
隐式转换(自动转换)
- 小类型 → 大类型
- 示例:
int a = 10; double b = a;
强制转换
- 大类型 → 小类型
- 语法:
(目标类型)值 - 示例:
double a = 3.14; int b = (int)a;
面试题:
// 题目1:short i = 11; 正确还是错误?
short i = 11; // 正确
// 原因:javac会判断11是否在short范围内,如果是就自动转换
// 题目2:short m = 10; short t = 11; short n = m + t; 结果如何?
short m = 10;
short t = 11;
short n = m + t; // 编译错误
// 原因:表达式中有变量时,short/char/byte会提升为int类型
// 正确写法:short n = (short)(m + t);
3.5 运算符
算术运算符:
| 运算符 | 说明 | 示例 |
|---|---|---|
+ | 加法/字符串连接 | a + b |
- | 减法 | a - b |
* | 乘法 | a * b |
/ | 除法 | a / b |
% | 取余 | a % b |
++ | 自增 | a++ 或 ++a |
-- | 自减 | a-- 或 --a |
注意事项:
- 整数除法结果仍为整数
- 取余结果符号与被除数相同
- 快速将整数转换为小数:乘以1.0
扩展算术运算符:
a += b; // 等价于 a = a + b;
a -= b; // 等价于 a = a - b;
a *= b; // 等价于 a = a * b;
a /= b; // 等价于 a = a / b;
a %= b; // 等价于 a = a % b;
自增自减运算符:
int i = 3;
int a = ++i; // 前自增:先加1再使用,a=4, i=4
int j = 3;
int b = j++; // 后自增:先使用再加1,b=3, j=4
逻辑运算符:
| 运算符 | 说明 | 特点 |
|---|---|---|
&& | 短路与 | 表达式1为false时,表达式2不执行 |
|| | 短路或 | 表达式1为true时,表达式2不执行 |
! | 逻辑非 | 取反 |
比较运算符:
| 运算符 | 说明 |
|---|---|
> | 大于 |
< | 小于 |
== | 等于 |
!= | 不等于 |
>= | 大于等于 |
<= | 小于等于 |
注意:
- 基本类型比较的是数值
- 引用类型比较的是地址
三目运算符:
语法:(表达式)?返回值1 : 返回值2;
示例:
boolean isGender = true;
char c1 = (isGender == true) ? '男' : '女';
4. 流程控制
4.1 if-else语句
语法格式:
1. 基本if语句:
if(条件表达式) {
// 语句块
}
2. if-else语句:
if(条件表达式) {
// 语句块1
} else {
// 语句块2
}
3. if-else if-else语句:
if(条件表达式1) {
// 语句块1
} else if(条件表达式2) {
// 语句块2
} else if(条件表达式3) {
// 语句块3
} else {
// 语句块4
}
注意:
- if不能省略,else if可以有0个或多个,else最多有一个
- if-else嵌套不宜超过3层
面试题:
boolean flag = true;
if(flag = false) { // 注意:这里是赋值,不是比较
System.out.println("A");
} else if(flag == false) {
System.out.println("B"); // 输出B
} else if(flag = true) {
System.out.println("C");
} else {
System.out.println("D");
}
4.2 switch-case语句
语法格式:
switch(表达式) {
case 值1:
// 语句块1
break;
case 值2:
// 语句块2
break;
// ...
default:
// 默认语句块
}
支持的数据类型:
- JDK 6.0及以下:byte、short、char、int
- JDK 7.0及以上:byte、short、char、int、long、String
注意事项:
- case后的值必须是常量
- break可以省略(会穿透)
- default可以省略
4.3 循环语句
1. while循环:
while(条件表达式) { // 先判断,后执行
// 循环体
}
2. do-while循环:
do { // 先执行,后判断
// 循环体
} while(条件表达式);
区别:
- while:先判断后执行,可能一次都不执行
- do-while:先执行后判断,至少执行一次
3. for循环:
for(初始化; 条件; 更新) { // 条件明确时使用
// 循环体
}
经典死循环:
// 方式1:while死循环
while(true) {
if(条件) break;
}
// 方式2:for死循环
for(;;) {
if(条件) break;
}
4.4 关键字
break和continue对比:
| 关键字 | 作用 | 使用场景 |
|---|---|---|
break | 终止循环,继续执行循环后的代码 | switch、循环 |
continue | 跳过当次循环,继续执行下一次循环 | 仅循环 |
示例:
// break示例
for(int i = 0; i < 10; i++) {
if(i == 5) break; // 当i=5时跳出循环
System.out.println(i);
}
// continue示例
for(int i = 0; i < 10; i++) {
if(i == 5) continue; // 跳过i=5的情况
System.out.println(i);
}
4.5 方法(函数)
概念: 某一个功能块
定义语法:
修饰符 返回值类型 方法名(数据类型 参数名, 数据类型 参数名, ...) {
// 方法体
return 返回值;
}
注意:
- 当方法没有返回值时,使用
void关键字占位 - 使用void后,return语句可以省略
方法调用:
// 同一类中调用:方法名(实参);
int result = max(10, 20);
// 不同类中调用:对象.方法名(实参);
int distance = point.distance(otherPoint);
形参和实参:
- 形参:形式参数,出现在方法定义的参数列表中
- 实参:实际参数,出现在方法调用的参数列表中
方法重载:
- 条件:方法名相同,参数列表不同(个数或类型)
- 注意:与返回值类型无关
- 本质:多态的一种体现形式
5. 数组
5.1 数组概念
定义: 一组相同数据类型的集合
特点:
- 类型相同
- 内存空间连续
5.2 数组语法
声明方式:
// 推荐方式
数据类型[] 数组名; // int[] arr; String[] pokers;
// 不推荐方式
数据类型 数组名[]; // int arr[]; String pokers[];
5.3 数组初始化
1. 静态初始化:
int[] array = {1, 2, 3, 4, 5, 6, 7};
String[] strs = {"A", "1", "2", "K", "10"};
2. 动态初始化:
// 第一种:不赋值
String[] rooms = new String[3]; // 创建长度为3的数组
boolean[] flags = new boolean[3];
// 第二种:赋值
String[] rs = new String[]{"单人间", "双人间", "商务房"};
int[] ars = new int[]{1, 2, 3};
5.4 数组遍历
数组元素访问:
数组名[下标]; // 下标从0开始
数组长度:
int len = array.length; // 获取数组长度
遍历数组:
// 使用for循环遍历
for(int index = 0; index < array.length; index++) {
int content = array[index];
System.out.println("数组下标为" + index + "的元素:" + content);
}
注意事项:
- 数组下标越界会抛出
ArrayIndexOutOfBoundsException - 推荐使用
index < array.length避免越界
5.5 数组工具类
System.arraycopy()方法:
// 作用:复制数组内容
System.arraycopy(src, srcPos, dest, destPos, length);
// 参数说明:
// src: 源数组
// srcPos: 源数组起始位置
// dest: 目标数组
// destPos: 目标数组起始位置
// length: 复制长度
Arrays.copyOf()方法:
// 作用:复制数组内容并返回新数组
int[] newArray = Arrays.copyOf(oldArray, newLength);
// 参数说明:
// oldArray: 原数组
// newLength: 新数组长度
自我复制示例:
// 数组扩容常用技巧
pokers = Arrays.copyOf(pokers, pokers.length + 1);
pokers[pokers.length - 1] = "大王";
6. 面向对象编程
6.1 面向对象基本概念
什么是对象?
- 对象是客观世界存在的物体
- 一切皆对象,看得见、看不见的都可以是对象
什么是面向对象?
- 以对象为主体,研究对象及对象之间的关系
- OOA/OOD:面向对象分析与设计
面向对象与面向过程的区别:
| 对比项 | 面向对象 | 面向过程 |
|---|---|---|
| 关注方向 | 对象、对象之间的关系 | 功能、功能之间的关系 |
| 内部细节 | 忽略实现细节,注重结果 | 关注内部实现细节 |
| 适用范围 | 大型项目(ERP、OA、电商平台) | 小型项目(驱动程序、芯片程序) |
6.2 面向对象的四大特征
- 封装:隐藏内部实现细节(如:发动机、存款)
- 继承:子类拥有父类的特性
- 多态:同一行为的不同表现形式(如:打酱油、打仗、打牌)
- 抽象:提取共同特征(如:时间概念)
6.3 面向对象相关概念
| 概念 | 说明 | 示例 |
|---|---|---|
| 类 | 类型、名词 | 动物、人、狗 |
| 对象 | 实例、东西 | 张三、小白 |
| 引用 | 保存对象地址的变量 | 张三(代词) |
| 属性 | 构成对象的不可分割部分 | 身高、体重、年龄 |
| 方法 | 行为、动作 | 吃、运动、笑 |
6.4 类的定义
语法格式:
修饰符 class 类名 {
// 属性
数据类型 属性名;
// 方法
返回值类型 方法名(参数列表) {
// 方法体
}
}
示例:
public class Book {
// 属性
String name;
String author;
double price;
// 方法
public void showInfo() {
System.out.println("书名:" + name);
System.out.println("作者:" + author);
System.out.println("价格:" + price);
}
}
6.5 对象的创建与使用
创建对象:
Book book = new Book();
访问属性:
book.name = "Java编程思想";
book.author = "Bruce Eckel";
book.price = 108.0;
调用方法:
book.showInfo();
6.6 局部变量与全局变量
局部变量:
- 定义在函数内部的变量
- 作用域在定义的函数内部
- 函数调用结束时自动销毁
- 保存在栈区
属性(全局变量):
- 定义在类的内部,与方法同级
- 对象的组成部分
- 保存在堆区
- 创建对象后自动赋默认值
6.7 构造器(构造方法)
概念: 用来创建对象的特殊方法
语法格式:
修饰符 类名(数据类型 参数名, ...) {
// 构造器代码
}
特点:
- 方法名和类名相同
- 无返回值
构造器重载:
条件:方法名相同,参数列表不同(个数或类型)
示例:
```java
public class Book {
public Book() { // 无参构造器
}public Book(String name) { // 有参构造器
this.name = name;
}public Book(String name, double price) { // 参数不同的构造器
this.name = name;
this.price = price;
}
}
### 6.8 this关键字
**概念:** 一个特殊的引用,保存的是当前对象的地址
**作用:**
1. 区分局部变量和属性
2. 在类的内部调用属性和方法
**示例:**
```java
public class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name; // this.name表示属性,name表示参数
this.age = age;
}
public void showInfo() {
this.printInfo(); // 调用本类方法
}
private void printInfo() {
System.out.println("姓名:" + name + ",年龄:" + age);
}
}
6.9 封装
概念: 隐藏内部实现细节
实现步骤:
将属性私有化
private int id; private String name;提供setter和getter方法
// setter方法:用于赋值
public void setId(int id) {
this.id = id;
}
// getter方法:用于取值
public int getId() {
return this.id;
}
访问控制修饰符:
| 修饰符 | 类内部 | 同包 | 子类 | 不同包 |
|---|---|---|---|---|
private | ✓ | ✗ | ✗ | ✗ |
[default] | ✓ | ✓ | ✗ | ✗ |
protected | ✓ | ✓ | ✓ | ✗ |
public | ✓ | ✓ | ✓ | ✓ |
6.10 继承
概念: 一个类拥有另一个类的特性(属性、方法)
判断方法: is-a(是)关系
- 学生是人 ✓
- 书是人 ✗
语法格式:
class 子类 extends 父类 {
}
示例:
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
class Student extends Person {
String school;
public Student(String name, int age, String school) {
super(name, age); // 调用父类构造器
this.school = school;
}
}
this和super对比:
| 关键字 | 作用 |
|---|---|
this() | 访问当前类的构造器 |
super() | 访问父类的构造器 |
this | 访问本类方法(含继承方法) |
super | 只访问父类方法 |
注意:
this()和super()必须出现在第一行- 不能同时出现在同一个构造器中
- 构造器中未显式调用时,javac会自动调用父类无参构造器
6.11 多态
分类:
- 行为多态:方法重载、方法重写
- 引用多态:父类引用指向子类对象
方法重写(Override):
- 子类中出现和父类一样的方法
- 要求:
- 方法名必须相同
- 参数列表必须相同
- 返回值类型必须相同
- 子类方法修饰范围 ≥ 父类方法
示例:
class Animal {
void speak() {
System.out.println("动物叫");
}
}
class Dog extends Animal {
@Override
void speak() {
System.out.println("汪汪汪");
}
}
引用多态示例:
Animal animal = new Dog(); // 父类引用指向子类对象
animal.speak(); // 输出:汪汪汪
6.12 方法签名
概念: 方法名 + 参数列表
就近原则:
- 实参类型 ≤ 形参类型(数据类型范围)
- 在满足理论前提下,选择最接近的
示例:
public class Test {
void test(short a) { }
void test(int a) { }
void test(double a) { }
public static void main(String[] args) {
Test t = new Test();
short s = 10;
t.test(s); // 调用test(short),因为最接近
}
}
7. 常用类
7.1 Scanner类
作用: 从控制台获取用户输入
使用步骤:
// 1. 导入包
import java.util.Scanner;
// 2. 创建Scanner对象
Scanner sc = new Scanner(System.in);
// 3. 获取输入
int num = sc.nextInt(); // 获取整数
double d = sc.nextDouble(); // 获取小数
String str = sc.next(); // 获取字符串
String line = sc.nextLine(); // 获取一行
// 4. 关闭扫描器
sc.close();
7.2 Random类
作用: 生成随机数
使用步骤:
// 1. 导入包
import java.util.Random;
// 2. 创建Random对象
Random ran = new Random();
// 3. 生成随机数
int num = ran.nextInt(10); // 生成0~9的随机数
int num2 = ran.nextInt(5) + 1; // 生成1~5的随机数
7.3 Arrays类
作用: 数组操作工具类
常用方法:
import java.util.Arrays;
// 1. 数组转字符串
String str = Arrays.toString(array);
// 2. 数组排序
Arrays.sort(array);
// 3. 数组复制
int[] newArray = Arrays.copyOf(oldArray, newLength);
// 4. 数组填充
Arrays.fill(array, value);
// 5. 二分查找
int index = Arrays.binarySearch(array, key);
7.4 String类
概念: 字符串常量,不可变
创建方式:
// 方式1:字面量
String str1 = "Hello";
// 方式2:构造方法
String str2 = new String("Hello");
常用方法:
| 方法 | 说明 |
|---|---|
length() | 获取字符串长度 |
charAt(int index) | 获取指定位置字符 |
indexOf(String str) | 查找子串位置,不存在返回-1 |
substring(int start) | 从start截取到末尾 |
substring(int start, int end) | 截取[start, end) |
trim() | 去除首尾空格 |
toLowerCase() | 转小写 |
toUpperCase() | 转大写 |
startsWith(String prefix) | 判断是否以prefix开头 |
endsWith(String suffix) | 判断是否以suffix结尾 |
equals(Object obj) | 判断内容是否相等 |
equalsIgnoreCase(String str) | 忽略大小写比较 |
split(String regex) | 按正则分割字符串 |
字符串比较:
String str1 = "Hello";
String str2 = "Hello";
// 使用equals比较内容
boolean isEqual = str1.equals(str2); // true
// 使用==比较地址
boolean isSame = (str1 == str2); // true(字面量在常量池)
7.5 StringBuilder和StringBuffer
区别:
String:不可变字符序列StringBuilder:可变字符序列,线程不安全,效率高StringBuffer:可变字符序列,线程安全,效率低
常用方法:
StringBuilder sb = new StringBuilder();
sb.append("Hello"); // 追加
sb.insert(0, "World"); // 插入
sb.delete(0, 5); // 删除
sb.replace(0, 5, "Java"); // 替换
sb.reverse(); // 反转
String result = sb.toString(); // 转为String
8. 集合框架
8.1 集合概述
为什么使用集合?
- 数组长度固定,集合长度动态
- 数组只能存储同类型,集合可以存储多种类型
- 集合提供了丰富的方法
集合体系结构:
Collection(接口)
├── List(接口) - 有序、可重复
│ ├── ArrayList
│ ├── LinkedList
│ └── Vector
├── Set(接口) - 无序、不可重复
│ ├── HashSet
│ ├── LinkedHashSet
│ └── TreeSet
└── Queue(接口) - 队列
├── ConcurrentLinkedQueue
└── ArrayDeque
Map(接口) - 键值对
├── HashMap
├── LinkedHashMap
├── TreeMap
└── Hashtable
└── Properties
8.2 List接口
特点:
- 有序的(插入顺序)
- 可以重复
- 可以有多个null
ArrayList vs Vector:
| 特性 | ArrayList | Vector |
|---|---|---|
| 线程安全 | 否 | 是 |
| 性能 | 高 | 低 |
| 扩容倍数 | 1.5倍 | 2倍 |
| 推荐使用 | ✓ | ✗ |
ArrayList示例:
import java.util.ArrayList;
// 创建ArrayList
ArrayList<String> list = new ArrayList<>();
// 添加元素
list.add("Apple");
list.add("Banana");
list.add(1, "Orange"); // 在指定位置插入
// 获取元素
String fruit = list.get(0);
// 修改元素
list.set(0, "Grape");
// 删除元素
list.remove(0); // 删除指定位置
list.remove("Apple"); // 删除指定对象
// 获取大小
int size = list.size();
// 判断是否包含
boolean contains = list.contains("Apple");
// 清空
list.clear();
LinkedList特点:
- 内部使用链表实现
- 插入删除效率高
- 查询效率低
8.3 Set接口
特点:
- 无序的
- 不可重复
- 只能有一个null
HashSet示例:
import java.util.HashSet;
HashSet<String> set = new HashSet<>();
// 添加元素(自动去重)
set.add("A");
set.add("B");
set.add("A"); // 重复,不会添加
// 判断包含
boolean contains = set.contains("A");
// 遍历
for(String item : set) {
System.out.println(item);
}
TreeSet特点:
- 基于树结构实现
- 自动排序(升序)
- 不可重复
8.4 Map接口
特点:
- 键值对(Key-Value)集合
- 键不可重复,值可以重复
- 键只能有一个null,值可以有多个null
HashMap示例:
import java.util.HashMap;
// 创建HashMap
HashMap<String, Integer> map = new HashMap<>();
// 添加键值对
map.put("张三", 90);
map.put("李四", 85);
map.put("王五", 95);
// 获取值
Integer score = map.get("张三");
// 删除
map.remove("李四");
// 判断包含
boolean hasKey = map.containsKey("张三");
boolean hasValue = map.containsValue(90);
// 获取大小
int size = map.size();
// 遍历
for(Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
Hashtable vs HashMap:
| 特性 | Hashtable | HashMap |
|---|---|---|
| 线程安全 | 是 | 否 |
| 效率 | 低 | 高 |
| null键值 | 不允许 | 允许 |
| 推荐 | ✗ | ✓ |
8.5 Collections工具类
作用: 集合操作的工具类
常用方法:
import java.util.Collections;
// 排序(升序)
Collections.sort(list);
// 反转
Collections.reverse(list);
// 二分查找(前提:已排序)
int index = Collections.binarySearch(list, key);
// 获取最大值/最小值
Object max = Collections.max(list);
Object min = Collections.min(list);
// 填充
Collections.fill(list, object);
// 洗牌(打乱顺序)
Collections.shuffle(list);
// 交换位置
Collections.swap(list, i, j);
// 转为线程安全
List<T> synchronizedList = Collections.synchronizedList(list);
9. 泛型与增强for循环
9.1 泛型编程
作用:
- 规定集合中保存的对象类型(只能是引用类型)
- 迭代器遍历时不需要强制类型转换
语法:
// 泛型类
ArrayList<String> list = new ArrayList<String>();
// 泛型方法(菱形运算符,JDK7+)
ArrayList<String> list = new ArrayList<>();
示例:
// 使用泛型的ArrayList
ArrayList<String> list = new ArrayList<>();
list.add("Hello");
list.add("World");
// 遍历时不需要类型转换
for(String str : list) {
System.out.println(str);
}
Map集合泛型:
Map<String, Integer> map = new HashMap<>();
map.put("张三", 90);
map.put("李四", 85);
// 遍历
for(Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
9.2 增强for循环(foreach)
作用: 替代迭代器遍历集合和数组
语法:
for(类型 变量名 : 集合/数组) {
// 循环体
}
示例:
// 遍历数组
int[] array = {1, 2, 3, 4, 5};
for(int num : array) {
System.out.println(num);
}
// 遍历集合
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
for(String str : list) {
System.out.println(str);
}
注意:
- 变量名就是从集合中获取的一个个对象
- 底层实现是迭代器,运行效率高于普通for循环
- 无法获取当前索引
10. 异常处理
10.1 异常概述
异常层次结构:
Throwable
├── Error(错误)
│ ├── OutOfMemoryError
│ └── StackOverflowError
└── Exception(异常)
├── RuntimeException(运行时异常)
│ ├── NullPointerException
│ ├── ArrayIndexOutOfBoundsException
│ └── ArithmeticException
└── 其他异常(编译时异常)
├── IOException
├── SQLException
└── ClassNotFoundException
10.2 常见异常
NullPointerException(空指针异常):
String str = null;
int len = str.length(); // 抛出NullPointerException
ArrayIndexOutOfBoundsException(数组越界):
int[] array = {1, 2, 3};
int num = array[5]; // 抛出ArrayIndexOutOfBoundsException
ArithmeticException(算术异常):
int result = 10 / 0; // 抛出ArithmeticException
10.3 异常处理机制
try-catch-finally语法:
try {
// 可能出现异常的代码
} catch(异常类型 变量名) {
// 异常处理代码
} catch(异常类型 变量名) {
// 异常处理代码
} finally {
// 无论是否异常都执行的代码
}
示例:
try {
int result = 10 / 0;
} catch(ArithmeticException e) {
System.out.println("算术异常:" + e.getMessage());
} finally {
System.out.println("finally块执行");
}
throws关键字(声明异常):
public void readFile() throws IOException {
// 可能抛出IOException的代码
}
throw关键字(手动抛出异常):
if(age < 0) {
throw new IllegalArgumentException("年龄不能为负");
}
11. IO流
11.1 IO流概述
流的概念:
- 输入流(Input):从外部读取数据到程序
- 输出流(Output):从程序写出数据到外部
流的分类:
按流向分:
├── 输入流:InputStream、Reader
└── 输出流:OutputStream、Writer
按单位分:
├── 字节流:InputStream、OutputStream(处理二进制文件)
└── 字符流:Reader、Writer(处理文本文件)
按角色分:
├── 节点流:直接连接介质(FileInputStream、FileReader)
└── 处理流:修饰节点流(BufferedInputStream、BufferedReader)
11.2 File类
作用: 表示文件或目录
常用方法:
import java.io.File;
File file = new File("D:/test.txt");
// 判断
boolean exists = file.exists(); // 是否存在
boolean isFile = file.isFile(); // 是否是文件
boolean isDirectory = file.isDirectory(); // 是否是目录
// 操作
boolean create = file.createNewFile(); // 创建文件
boolean mkdir = file.mkdir(); // 创建目录
boolean delete = file.delete(); // 删除
// 信息
String name = file.getName(); // 获取名称
long length = file.length(); // 获取大小(字节)
long modified = file.lastModified(); // 最后修改时间
// 目录内容
File[] files = file.listFiles(); // 获取目录下所有文件
11.3 字节流
FileInputStream(文件输入流):
import java.io.FileInputStream;
// 读取单个字节
FileInputStream fis = new FileInputStream("input.txt");
int data = fis.read(); // 读取一个字节,返回-1表示结束
fis.close();
// 读取多个字节
byte[] buffer = new byte[1024];
int len = fis.read(buffer); // 返回实际读取的字节数
fis.close();
FileOutputStream(文件输出流):
import java.io.FileOutputStream;
// 写入数据
FileOutputStream fos = new FileOutputStream("output.txt");
fos.write(65); // 写入单个字节(ASCII码)
fos.close();
// 追加模式
FileOutputStream fos = new FileOutputStream("output.txt", true);
缓冲字节流:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("input.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("output.txt"));
// 使用缓冲区提高效率
byte[] buffer = new byte[8192];
int len;
while((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
bis.close();
bos.close();
11.4 字符流
FileReader(文件读取器):
import java.io.FileReader;
FileReader fr = new FileReader("input.txt");
int ch = fr.read(); // 读取一个字符
fr.close();
// 读取多个字符
char[] buffer = new char[1024];
int len = fr.read(buffer);
fr.close();
FileWriter(文件写入器):
import java.io.FileWriter;
FileWriter fw = new FileWriter("output.txt");
fw.write("Hello, World!");
fw.close();
// 追加模式
FileWriter fw = new FileWriter("output.txt", true);
BufferedReader(缓冲读取器):
import java.io.BufferedReader;
BufferedReader br = new BufferedReader(new FileReader("input.txt"));
String line;
while((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
BufferedWriter(缓冲写入器):
import java.io.BufferedWriter;
BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"));
bw.write("Hello");
bw.newLine(); // 写换行符
bw.write("World");
bw.close();
11.5 转换流
InputStreamReader(输入转换流):
import java.io.InputStreamReader;
import java.io.FileInputStream;
// 指定字符集
InputStreamReader isr = new InputStreamReader(
new FileInputStream("input.txt"),
"UTF-8"
);
OutputStreamWriter(输出转换流):
import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("output.txt"),
"UTF-8"
);
11.6 打印流
PrintWriter:
import java.io.PrintWriter;
PrintWriter pw = new PrintWriter("output.txt");
pw.println("Hello"); // 自动换行
pw.print("World");
pw.close();
12. 数据库编程
12.1 数据库概述
数据库组成:
- DBMS(Database Manager System):数据库管理系统
- Data文件:存储数据的文件
常用数据库:
- 关系型数据库:Oracle、DB2、MySQL、SQL Server
- NoSQL数据库:MongoDB、HBase
12.2 JDBC基础
JDBC(Java Database Connectivity): Java数据库连接
JDBC驱动:
// Oracle驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
// MySQL驱动
Class.forName("com.mysql.jdbc.Driver");
连接数据库:
import java.sql.Connection;
import java.sql.DriverManager;
// Oracle连接
String url = "jdbc:oracle:thin:@localhost:1521:orcl";
String user = "scott";
String password = "tiger";
Connection conn = DriverManager.getConnection(url, user, password);
// MySQL连接
String url = "jdbc:mysql://localhost:3306/mydb";
String user = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, user, password);
执行SQL语句:
import java.sql.Statement;
import java.sql.ResultSet;
// 创建Statement
Statement stmt = conn.createStatement();
// 执行查询
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
while(rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
System.out.println(id + ":" + name);
}
// 执行增删改
int rows = stmt.executeUpdate("UPDATE users SET name='Tom' WHERE id=1");
// 关闭资源
rs.close();
stmt.close();
conn.close();
12.3 PreparedStatement
特点:
- 预编译SQL语句
- 防止SQL注入
- 性能更好
使用示例:
import java.sql.PreparedStatement;
String sql = "INSERT INTO users(id, name, age) VALUES(?, ?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
// 设置参数
pstmt.setInt(1, 1);
pstmt.setString(2, "张三");
pstmt.setInt(3, 20);
// 执行
int rows = pstmt.executeUpdate();
pstmt.close();
13. Web前端基础
13.1 HTML基础
HTML(HyperText Markup Language): 超文本标记语言
基本结构:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>网页标题</title>
</head>
<body>
<!-- 页面内容 -->
</body>
</html>
常用标签:
| 标签 | 说明 |
|---|---|
<h1>~`` | 标题标签 |
<p> | 段落标签 |
<br> | 换行 |
<hr> | 水平线 |
<font> | 字体标签 |
<b> | 粗体 |
<i> | 斜体 |
<u> | 下划线 |
<img> | 图片 |
<a> | 链接 |
<table> | 表格 |
<form> | 表单 |
表单示例:
<form action="login" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="pwd"/><br/>
<input type="submit" value="提交"/>
<input type="reset" value="重置"/>
</form>
13.2 CSS样式
CSS(Cascading Style Sheets): 层叠样式表
三种引入方式:
内嵌式(不推荐)
<div style="border:1px solid red; width:200px;">内容</div>内联式
<style type="text/css"> .myClass { color: red; font-size: 16px; } </style>外部引入(推荐)
<link type="text/css" rel="stylesheet" href="styles.css"/>
常用选择器:
| 选择器 | 语法 | 说明 |
|---|---|---|
| ID选择器 | #id值{} | 通过ID选择 |
| 类选择器 | .类名{} | 通过class选择 |
| 标签选择器 | 标签名{} | 通过标签名选择 |
| 派生选择器 | 父标签 子标签{} | 选择子标签 |
13.3 JavaScript基础
JavaScript特点:
- 运行在浏览器上
- 弱类型语言
- 动态改变HTML显示效果
变量声明:
var i = 10; // 数字
var str = "Hello"; // 字符串
var flag = true; // 布尔值
函数定义:
// 方式1:函数声明
function add(a, b) {
return a + b;
}
// 方式2:函数表达式
var add = function(a, b) {
return a + b;
};
// 方式3:匿名函数
var add = new Function("a", "b", "return a + b;");
常用对象:
// Array对象
var arr = [1, 2, 3, 4, 5];
arr.push(6); // 添加元素
arr.pop(); // 删除最后一个元素
arr.sort(); // 排序
// String对象
var str = "Hello World";
var len = str.length;
var sub = str.substring(0, 5);
// Date对象
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth() + 1; // 0-11,需要+1
// Math对象
var num = Math.random(); // 随机数0~1
var max = Math.max(1, 2, 3);
14. Spring框架
14.1 Spring简介
Spring是什么?
- 轻量级Java EE应用框架
- IOC(控制反转)和AOP(面向切面编程)容器框架
Spring特点:
- 降低组件之间的耦合度
- 提供众多服务(事务管理、持久层集成等)
- 单例模式
- AOP技术
- 对常用API(JDBC、JavaMail、远程调用等)提供封装
14.2 IOC(控制反转)
概念:
- 传统方式:程序创建对象
- IOC方式:Spring容器创建和管理对象
依赖注入(DI):
- Setter注入
- 构造器注入
- 接口注入
配置方式:
<!-- XML配置 -->
<bean id="userService" class="com.example.UserService">
<property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.example.UserDaoImpl"/>
14.3 AOP(面向切面编程)
概念: 将公共逻辑从业务代码中分离出来
核心概念:
- 切面(Aspect):横切关注点的模块化
- 连接点(JoinPoint):程序执行的某个位置
- 切点(Pointcut):匹配连接点的表达式
- 通知(Advice):切面在特定连接点执行的动作
- 目标(Target):被通知的对象
- 代理(Proxy):AOP创建的对象
通知类型:
- 前置通知(Before)
- 后置通知(AfterReturning)
- 异常通知(AfterThrowing)
- 最终通知(After)
- 环绕通知(Around)
配置示例:
<aop:config>
<aop:aspect ref="logAspect">
<aop:before method="before" pointcut="execution(* com.example.*.*(..))"/>
<aop:after-returning method="after" pointcut="execution(* com.example.*.*(..))"/>
</aop:aspect>
</aop:config>
15. MyBatis框架
15.1 MyBatis简介
MyBatis是什么?
- 优秀的持久层框架
- 支持定制化SQL、存储过程和高级映射
- 避免了几乎所有的JDBC代码和手动参数设置
ORM(Object-Relation Mapping): 对象关系映射
15.2 MyBatis开发步骤
1. 导入jar包
- mybatis-x.x.x.jar
- 数据库驱动jar包
2. 创建配置文件
<!-- mybatis-config.xml -->
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
<property name="username" value="scott"/>
<property name="password" value="tiger"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/example/UserMapper.xml"/>
</mappers>
</configuration>
3. 创建映射文件
<!-- UserMapper.xml -->
<mapper namespace="com.example.UserMapper">
<select id="selectUser" resultType="com.example.User">
SELECT * FROM users WHERE id = #{id}
</select>
<insert id="insertUser" parameterType="com.example.User">
INSERT INTO users(id, name) VALUES(#{id}, #{name})
</insert>
</mapper>
4. 使用MyBatis
// 创建SqlSessionFactory
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(Resources.getResourceAsStream("mybatis-config.xml"));
// 创建SqlSession
SqlSession session = factory.openSession();
// 执行SQL
User user = session.selectOne("com.example.UserMapper.selectUser", 1);
session.commit(); // 提交事务
session.close(); // 关闭会话
15.3 MyBatis核心API
SqlSessionFactoryBuilder:
SqlSessionFactory build(InputStream inputStream)
SqlSessionFactory:
SqlSession openSession() // 创建会话(不自动提交)
SqlSession openSession(boolean autoCommit) // 创建会话(自动提交)
SqlSession:
Object selectOne(String statement) // 查询单个对象
List selectList(String statement) // 查询多个对象
int insert(String statement) // 插入
int update(String statement) // 更新
int delete(String statement) // 删除
void commit() // 提交事务
void rollback() // 回滚事务
void close() // 关闭会话
15.4 动态SQL
if标签:
<select id="selectUsers" resultType="User">
SELECT * FROM users
WHERE 1=1
<if test="name != null">
AND name LIKE #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</select>
foreach标签:
<select id="selectUsers" resultType="User">
SELECT * FROM users
WHERE id IN
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
16. SpringMVC框架
16.1 SpringMVC简介
SpringMVC是什么?
- Spring提供的Web框架
- 基于MVC设计模式
- 轻量级、灵活、易扩展
MVC设计模式:
- Model(模型):数据模型
- View(视图):页面展示
- Controller(控制器):处理请求
16.2 SpringMVC开发步骤
1. 导入jar包
- spring-webmvc-x.x.x.jar
- spring-web-x.x.x.jar
- 相关依赖包
2. 配置web.xml
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
3. 创建配置文件
<!-- springmvc.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="...">
<!-- 扫描控制器 -->
<context:component-scan base-package="com.example.controller"/>
<!-- 开启MVC注解 -->
<mvc:annotation-driven/>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
4. 创建控制器
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/list")
public String list(Model model) {
// 获取用户列表
List<User> users = userService.findAll();
model.addAttribute("users", users);
return "user/list"; // 返回视图名称
}
@RequestMapping("/save")
public String save(User user) {
userService.save(user);
return "redirect:/user/list"; // 重定向
}
}
16.3 常用注解
| 注解 | 说明 |
|---|---|
@Controller | 标识控制器类 |
@RequestMapping | 映射请求URL |
@RequestParam | 绑定请求参数 |
@PathVariable | 绑定路径变量 |
@RequestBody | 绑定请求体 |
@ResponseBody | 返回JSON |
@ModelAttribute | 绑定模型数据 |
@SessionAttributes | 设置会话属性 |
16.4 数据绑定
绑定请求参数:
@RequestMapping("/login")
public String login(@RequestParam("username") String username,
@RequestParam("password") String password) {
// 登录逻辑
return "success";
}
绑定POJO对象:
@RequestMapping("/save")
public String save(User user) {
userService.save(user);
return "success";
}
绑定日期类型:
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
📝 附录
常用面试题
1. ==和equals的区别
==:比较地址(引用类型)或数值(基本类型)equals:比较内容(需要重写)
2. String、StringBuilder、StringBuffer的区别
String:不可变,线程安全StringBuilder:可变,线程不安全,效率高StringBuffer:可变,线程安全,效率低
3. ArrayList和LinkedList的区别
ArrayList:基于数组,查询快,增删慢LinkedList:基于链表,增删快,查询慢
4. HashMap和Hashtable的区别
HashMap:线程不安全,允许null键值Hashtable:线程安全,不允许null键值
学习建议
- 基础要扎实:Java基础是学习框架的前提
- 多动手实践:理论结合实践,多做项目
- 阅读源码:理解框架内部实现原理
- 持续学习:技术更新快,保持学习热情
版权声明
本文为 程序员青阳 原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文链接及本声明。