Java学习笔记

📚 目录结构


1. Java简介

1.1 什么是Java?

Java是一门编程语言,是一组有序的指令集,用于驱动计算机工作。

编程语言发展史:

  • 第一代语言:机器语言(0,1)
  • 第二代语言:汇编语言(mov、add、寄存器)
  • 第三代语言:高级语言
    • 面向过程:C(指针)、C++(游戏引擎)
    • 面向对象:Java、C#、Objective-C、JavaScript
  • 第四代语言:SQL

1.2 Java能做什么?

  1. 企业级开发:OA、ERP、教务系统、电商平台(淘宝)
  2. 移动互联网:App、车联网、互联网电视、智能家居
  3. 大数据:数据挖掘与分析

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技术体系:

技术平台说明
JavaSEJava标准版,基础语法
JavaEEJava企业版,用于企业级开发(Web应用)
JavaMEJava微型版,用于移动设备开发

1.6 JDK目录结构

jdk/
├── bin/          开发过程中依赖的工具包(命令)
├── db/           数据方面的案例
├── demo/         Java新功能的案例
├── include/      Java底层是C语言
├── jre/          运行环境
├── lib/          库文件
└── src.zip       Java源代码

2. 开发环境搭建

2.1 JDK安装步骤

  1. 下载JDK安装包(推荐Oracle JDK)
  2. 按提示一步步安装即可
  3. 配置环境变量

2.2 环境变量配置

Windows系统配置步骤:

  1. 右击”计算机” → “高级系统设置”
  2. 在”系统变量”中找到Path变量
  3. 在变量值的最前面输入JDK的bin目录路径,并以;结尾
# 示例:C:\Program Files\Java\jdk1.8.0\bin;
  1. 点击”确定”保存

验证安装:

# 打开命令行窗口,输入以下命令
java -version
javac -version

2.3 IDE开发工具

MyEclipse/Eclipse安装与配置:

  1. 下载并安装IDE
  2. 配置JRE路径:Window → Preferences → Java → Installed JREs
  3. 配置工作空间编码: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等
    ├── 接口
    └── 数组

基本数据类型详细表:

类型取值范围默认值占用字节说明
booleantrue|falsefalse1位布尔类型
byte-2⁷ ~ 2⁷-1 (-128 ~ 127)01字节字节型
short-2¹⁵ ~ 2¹⁵-1 (-32768 ~ 32767)02字节短整型
char0~65535 (Unicode字符集)\u00002字节字符型
int-2³¹ ~ 2³¹-104字节整型(默认)
long-2⁶³ ~ 2⁶³-10L8字节长整型
float±3.4e38 (7位有效数字)0.0f4字节单精度浮点
double±1.8e308 (15位有效数字)0.0d8字节双精度浮点(默认)

重要提示:

  1. 整数的默认类型是int类型

    long k;
    k = 123123213L;  // 必须加L或l
    
  2. 小数的默认类型是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

两种类型转换方式:

  1. 隐式转换(自动转换)

    • 小类型 → 大类型
    • 示例:int a = 10; double b = a;
  2. 强制转换

    • 大类型 → 小类型
    • 语法:(目标类型)值
    • 示例: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. 整数除法结果仍为整数
  2. 取余结果符号与被除数相同
  3. 快速将整数转换为小数:乘以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

注意事项:

  1. case后的值必须是常量
  2. break可以省略(会穿透)
  3. 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 返回值;
}

注意:

  1. 当方法没有返回值时,使用void关键字占位
  2. 使用void后,return语句可以省略

方法调用:

// 同一类中调用:方法名(实参);
int result = max(10, 20);

// 不同类中调用:对象.方法名(实参);
int distance = point.distance(otherPoint);

形参和实参:

  • 形参:形式参数,出现在方法定义的参数列表中
  • 实参:实际参数,出现在方法调用的参数列表中

方法重载:

  • 条件:方法名相同,参数列表不同(个数或类型)
  • 注意:与返回值类型无关
  • 本质:多态的一种体现形式

5. 数组

5.1 数组概念

定义: 一组相同数据类型的集合

特点:

  1. 类型相同
  2. 内存空间连续

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 面向对象的四大特征

  1. 封装:隐藏内部实现细节(如:发动机、存款)
  2. 继承:子类拥有父类的特性
  3. 多态:同一行为的不同表现形式(如:打酱油、打仗、打牌)
  4. 抽象:提取共同特征(如:时间概念)

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 构造器(构造方法)

概念: 用来创建对象的特殊方法

语法格式:

修饰符 类名(数据类型 参数名, ...) {
    // 构造器代码
}

特点:

  1. 方法名和类名相同
  2. 无返回值

构造器重载:

  • 条件:方法名相同,参数列表不同(个数或类型)

  • 示例:
    ```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 封装

概念: 隐藏内部实现细节

实现步骤:

  1. 将属性私有化

    private int id;
    private String name;
    
  2. 提供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只访问父类方法

注意:

  1. this()super()必须出现在第一行
  2. 不能同时出现在同一个构造器中
  3. 构造器中未显式调用时,javac会自动调用父类无参构造器

6.11 多态

分类:

  1. 行为多态:方法重载、方法重写
  2. 引用多态:父类引用指向子类对象

方法重写(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接口

特点:

  1. 有序的(插入顺序)
  2. 可以重复
  3. 可以有多个null

ArrayList vs Vector:

特性ArrayListVector
线程安全
性能
扩容倍数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接口

特点:

  1. 无序的
  2. 不可重复
  3. 只能有一个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接口

特点:

  1. 键值对(Key-Value)集合
  2. 键不可重复,值可以重复
  3. 键只能有一个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:

特性HashtableHashMap
线程安全
效率
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 泛型编程

作用:

  1. 规定集合中保存的对象类型(只能是引用类型)
  2. 迭代器遍历时不需要强制类型转换

语法:

// 泛型类
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);
}

注意:

  1. 变量名就是从集合中获取的一个个对象
  2. 底层实现是迭代器,运行效率高于普通for循环
  3. 无法获取当前索引

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

特点:

  1. 预编译SQL语句
  2. 防止SQL注入
  3. 性能更好

使用示例:

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): 层叠样式表

三种引入方式:

  1. 内嵌式(不推荐)

    <div style="border:1px solid red; width:200px;">内容</div>
    
  2. 内联式

    <style type="text/css">
     .myClass {
         color: red;
         font-size: 16px;
     }
    </style>
    
  3. 外部引入(推荐)

    <link type="text/css" rel="stylesheet" href="styles.css"/>
    

常用选择器:

选择器语法说明
ID选择器#id值{}通过ID选择
类选择器.类名{}通过class选择
标签选择器标签名{}通过标签名选择
派生选择器父标签 子标签{}选择子标签

13.3 JavaScript基础

JavaScript特点:

  1. 运行在浏览器上
  2. 弱类型语言
  3. 动态改变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特点:

  1. 降低组件之间的耦合度
  2. 提供众多服务(事务管理、持久层集成等)
  3. 单例模式
  4. AOP技术
  5. 对常用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键值

学习建议

  1. 基础要扎实:Java基础是学习框架的前提
  2. 多动手实践:理论结合实践,多做项目
  3. 阅读源码:理解框架内部实现原理
  4. 持续学习:技术更新快,保持学习热情

本文为 程序员青阳 原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文链接及本声明。

原文链接:https://heliufang.github.io/posts/b6543913/index.html