Java 基础笔记
1. Java 简介
1.1 什么是 Java?
Java 是一种面向对象的编程语言,由 Sun Microsystems(现在是 Oracle)开发。它的设计目标是:
- Write Once, Run Anywhere (WORA) - 一次编写,到处运行
- 简单、面向对象、分布式、健壮、安全、平台无关、可移植、高性能
- 多线程、动态
1.2 Java 平台
- Java SE (Standard Edition) - 标准版,用于开发桌面应用
- Java EE (Enterprise Edition) - 企业版,用于开发企业级应用(现已迁移到 Jakarta EE)
- Java ME (Micro Edition) - 微型版,用于嵌入式设备(已被 Android 取代)
1.3 Java 版本历史
- Java 8 (2014) - Lambda 表达式、Stream API、Optional 等
- Java 11 (2018) - 长期支持版本 (LTS)
- Java 17 (2021) - 最新长期支持版本 (LTS)
- Java 21 (2023) - 最新特性版本
2. Java 开发环境搭建
2.1 JDK、JRE、JVM 区别
- JVM (Java Virtual Machine) - Java 虚拟机,负责执行 Java 字节码
- JRE (Java Runtime Environment) - Java 运行时环境,包含 JVM 和核心类库
- JDK (Java Development Kit) - Java 开发工具包,包含 JRE 和开发工具
2.2 安装 JDK
- 下载 JDK:访问 Oracle 官网 或 OpenJDK
- 安装 JDK,注意安装路径
- 配置环境变量:
JAVA_HOME- JDK 安装路径PATH- 添加%JAVA_HOME%\bin
- 验证安装:bash
java -version javac -versionjava -version javac -version
2.3 开发工具
- IDE:IntelliJ IDEA(推荐)、Eclipse、NetBeans
- 文本编辑器:VS Code + Java 插件、Sublime Text
3. Java 基本语法
3.1 第一个 Java 程序
// HelloWorld.java - 类名必须与文件名一致
public class HelloWorld {
// main 方法是程序入口点
public static void main(String[] args) {
// 输出语句
System.out.println("Hello, Java!");
}
}// HelloWorld.java - 类名必须与文件名一致
public class HelloWorld {
// main 方法是程序入口点
public static void main(String[] args) {
// 输出语句
System.out.println("Hello, Java!");
}
}3.2 编译和运行
# 编译:将 .java 文件编译为 .class 字节码文件
javac HelloWorld.java
# 运行:执行字节码文件
java HelloWorld# 编译:将 .java 文件编译为 .class 字节码文件
javac HelloWorld.java
# 运行:执行字节码文件
java HelloWorld3.3 注释
// 单行注释
/*
* 多行注释
*/
/**
* 文档注释 - 用于生成 API 文档
* @author 作者
*/// 单行注释
/*
* 多行注释
*/
/**
* 文档注释 - 用于生成 API 文档
* @author 作者
*/3.4 标识符和关键字
标识符规则:
- 由字母、数字、下划线 (_) 和美元符号 ($) 组成
- 不能以数字开头
- 区分大小写
- 不能使用 Java 关键字
常用关键字:
public,private,protected- 访问修饰符class,interface,enum- 类型定义static,final,abstract- 修饰符if,else,for,while,switch- 控制流return,break,continue- 跳转语句
4. 数据类型
4.1 基本数据类型
Java 有 8 种基本数据类型:
| 类型 | 大小 | 范围 | 默认值 | 示例 |
|---|---|---|---|---|
byte | 1字节 | -128 到 127 | 0 | byte b = 100; |
short | 2字节 | -32768 到 32767 | 0 | short s = 1000; |
int | 4字节 | -2^31 到 2^31-1 | 0 | int i = 100000; |
long | 8字节 | -2^63 到 2^63-1 | 0L | long l = 100000L; |
float | 4字节 | 单精度浮点数 | 0.0f | float f = 3.14f; |
double | 8字节 | 双精度浮点数 | 0.0d | double d = 3.1415926; |
char | 2字节 | Unicode 字符 | '\u0000' | char c = 'A'; |
boolean | 1位 | true 或 false | false | boolean b = true; |
4.2 引用数据类型
- 类 (Class):如
String,Integer - 接口 (Interface)
- 数组 (Array)
- 枚举 (Enum)
- 注解 (Annotation)
示例:
// 字符串
String str = "Hello";
// 数组
int[] arr = {1, 2, 3};
// 包装类
Integer num = 100;// 字符串
String str = "Hello";
// 数组
int[] arr = {1, 2, 3};
// 包装类
Integer num = 100;4.3 类型转换
自动类型转换(小转大):
int i = 100;
double d = i; // 自动转换int i = 100;
double d = i; // 自动转换强制类型转换(大转小):
double d = 3.14;
int i = (int) d; // 强制转换,结果为 3double d = 3.14;
int i = (int) d; // 强制转换,结果为 35. 变量和常量
5.1 变量
定义变量:
// 语法:数据类型 变量名 = 值;
int age = 25;
String name = "Java";// 语法:数据类型 变量名 = 值;
int age = 25;
String name = "Java";变量作用域:
- 局部变量:在方法或代码块中定义,必须初始化
- 成员变量:在类中定义,有默认值
- 静态变量:使用
static修饰,属于类
5.2 常量
定义常量:使用 final 修饰
final int MAX_AGE = 120;
final double PI = 3.1415926;final int MAX_AGE = 120;
final double PI = 3.1415926;6. 运算符
6.1 算术运算符
+ - * / % // 加减乘除余
++ -- // 自增自减+ - * / % // 加减乘除余
++ -- // 自增自减6.2 关系运算符
== != > < >= <= // 等于、不等于、大于、小于、大于等于、小于等于== != > < >= <= // 等于、不等于、大于、小于、大于等于、小于等于6.3 逻辑运算符
&& || ! // 与、或、非
& | ^ // 位与、位或、位异或&& || ! // 与、或、非
& | ^ // 位与、位或、位异或6.4 赋值运算符
= += -= *= /= %= // 赋值、加赋值、减赋值等= += -= *= /= %= // 赋值、加赋值、减赋值等6.5 条件运算符(三元运算符)
// 语法:条件 ? 表达式1 : 表达式2
int max = a > b ? a : b;// 语法:条件 ? 表达式1 : 表达式2
int max = a > b ? a : b;7. 控制流语句
7.1 条件语句
if-else:
if (condition) {
// 条件为真时执行
} else if (anotherCondition) {
// 另一个条件为真时执行
} else {
// 所有条件为假时执行
}if (condition) {
// 条件为真时执行
} else if (anotherCondition) {
// 另一个条件为真时执行
} else {
// 所有条件为假时执行
}switch:
switch (variable) {
case value1:
// 代码
break;
case value2:
// 代码
break;
default:
// 默认代码
}switch (variable) {
case value1:
// 代码
break;
case value2:
// 代码
break;
default:
// 默认代码
}7.2 循环语句
for 循环:
// 传统 for 循环
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
// 增强 for 循环(for-each)
int[] arr = {1, 2, 3};
for (int num : arr) {
System.out.println(num);
}// 传统 for 循环
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
// 增强 for 循环(for-each)
int[] arr = {1, 2, 3};
for (int num : arr) {
System.out.println(num);
}while 循环:
while (condition) {
// 循环体
}while (condition) {
// 循环体
}do-while 循环:
do {
// 循环体
} while (condition);do {
// 循环体
} while (condition);7.3 跳转语句
break:跳出循环或 switchcontinue:跳过当前循环,进入下一次循环return:从方法中返回
8. 面向对象编程 (OOP)
8.1 类和对象
类:是对象的模板,定义了对象的属性和方法 对象:是类的实例
定义类:
// 类的定义
public class Person {
// 属性(成员变量)
private String name;
private int age;
// 构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 方法(成员方法)
public void sayHello() {
System.out.println("Hello, my name is " + name + ", I'm " + age + " years old.");
}
// getter 和 setter 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}// 类的定义
public class Person {
// 属性(成员变量)
private String name;
private int age;
// 构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 方法(成员方法)
public void sayHello() {
System.out.println("Hello, my name is " + name + ", I'm " + age + " years old.");
}
// getter 和 setter 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}创建对象:
// 创建对象
Person person = new Person("Java", 25);
// 调用方法
person.sayHello();
// 使用 getter/setter
person.setName("Java 17");
System.out.println(person.getName());// 创建对象
Person person = new Person("Java", 25);
// 调用方法
person.sayHello();
// 使用 getter/setter
person.setName("Java 17");
System.out.println(person.getName());8.2 封装
封装是将数据和操作数据的方法绑定在一起,对外部隐藏实现细节。
访问修饰符:
public:公开,任何类都可以访问protected:受保护,同一包或子类可以访问default(默认):同一包可以访问private:私有,只有本类可以访问
8.3 继承
继承允许一个类(子类)继承另一个类(父类)的属性和方法。
语法:
// 父类
public class Animal {
public void eat() {
System.out.println("Eating...");
}
}
// 子类继承父类
public class Dog extends Animal {
public void bark() {
System.out.println("Barking...");
}
}
// 使用
Dog dog = new Dog();
dog.eat(); // 继承自父类
dog.bark(); // 子类自己的方法// 父类
public class Animal {
public void eat() {
System.out.println("Eating...");
}
}
// 子类继承父类
public class Dog extends Animal {
public void bark() {
System.out.println("Barking...");
}
}
// 使用
Dog dog = new Dog();
dog.eat(); // 继承自父类
dog.bark(); // 子类自己的方法特点:
- Java 单继承:一个类只能有一个直接父类
- 可以多层继承
- 使用
super关键字访问父类成员
8.4 多态
多态是指同一行为的不同表现形式。
实现方式:
- 方法重载(Overloading):同一类中,方法名相同,参数不同
- 方法重写(Overriding):子类重写父类的方法
- 接口实现
示例:
// 父类引用指向子类对象
Animal animal = new Dog();
animal.eat(); // 调用子类的 eat 方法(如果重写了)// 父类引用指向子类对象
Animal animal = new Dog();
animal.eat(); // 调用子类的 eat 方法(如果重写了)8.5 抽象类和接口
抽象类:使用 abstract 修饰,不能实例化,用于定义模板
abstract class Shape {
abstract double getArea(); // 抽象方法,没有实现
void printShape() {
System.out.println("This is a shape.");
}
}
class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
double getArea() {
return Math.PI * radius * radius;
}
}abstract class Shape {
abstract double getArea(); // 抽象方法,没有实现
void printShape() {
System.out.println("This is a shape.");
}
}
class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
double getArea() {
return Math.PI * radius * radius;
}
}接口:使用 interface 修饰,定义行为规范
interface Drawable {
void draw(); // 抽象方法(Java 8+ 可以有默认方法)
default void defaultMethod() {
System.out.println("Default method.");
}
}
class Rectangle implements Drawable {
@Override
public void draw() {
System.out.println("Drawing a rectangle.");
}
}interface Drawable {
void draw(); // 抽象方法(Java 8+ 可以有默认方法)
default void defaultMethod() {
System.out.println("Default method.");
}
}
class Rectangle implements Drawable {
@Override
public void draw() {
System.out.println("Drawing a rectangle.");
}
}9. 数组
9.1 数组定义和初始化
定义数组:
// 方式1:声明并初始化
int[] arr1 = {1, 2, 3, 4, 5};
// 方式2:声明后初始化
int[] arr2 = new int[5]; // 初始化为默认值 0
arr2[0] = 1;
arr2[1] = 2;
// 方式3:声明时指定长度并初始化
int[] arr3 = new int[]{1, 2, 3, 4, 5};// 方式1:声明并初始化
int[] arr1 = {1, 2, 3, 4, 5};
// 方式2:声明后初始化
int[] arr2 = new int[5]; // 初始化为默认值 0
arr2[0] = 1;
arr2[1] = 2;
// 方式3:声明时指定长度并初始化
int[] arr3 = new int[]{1, 2, 3, 4, 5};9.2 数组操作
访问数组元素:
int firstElement = arr1[0]; // 获取第一个元素
arr1[0] = 100; // 修改第一个元素int firstElement = arr1[0]; // 获取第一个元素
arr1[0] = 100; // 修改第一个元素数组长度:
int length = arr1.length;int length = arr1.length;遍历数组:
// for 循环遍历
for (int i = 0; i < arr1.length; i++) {
System.out.println(arr1[i]);
}
// 增强 for 循环遍历
for (int num : arr1) {
System.out.println(num);
}// for 循环遍历
for (int i = 0; i < arr1.length; i++) {
System.out.println(arr1[i]);
}
// 增强 for 循环遍历
for (int num : arr1) {
System.out.println(num);
}9.3 多维数组
二维数组示例:
// 定义二维数组
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// 访问元素
int element = matrix[0][1]; // 2
// 遍历二维数组
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}// 定义二维数组
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// 访问元素
int element = matrix[0][1]; // 2
// 遍历二维数组
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}10. 字符串
10.1 String 类
String 是不可变的字符序列。
创建字符串:
String str1 = "Hello"; // 字符串常量池
String str2 = new String("Hello"); // 堆内存String str1 = "Hello"; // 字符串常量池
String str2 = new String("Hello"); // 堆内存常用方法:
String str = "Hello, Java!";
// 长度
int length = str.length(); // 12
// 索引
char ch = str.charAt(0); // 'H'
// 子串
String substr = str.substring(7); // "Java!"
String substr2 = str.substring(7, 11); // "Java"
// 拼接
String newStr = str + " Welcome!"; // "Hello, Java! Welcome!"
// 查找
int index = str.indexOf("Java"); // 7
int lastIndex = str.lastIndexOf('a'); // 9
// 替换
String replaced = str.replace("Java", "World"); // "Hello, World!"
// 分割
String[] parts = str.split(", "); // ["Hello", "Java!"]
// 转换大小写
String upper = str.toUpperCase(); // "HELLO, JAVA!"
String lower = str.toLowerCase(); // "hello, java!"
// 去除空格
String trimStr = " Hello ".trim(); // "Hello"
// 比较
boolean equals = str.equals("Hello, Java!"); // true
boolean equalsIgnoreCase = str.equalsIgnoreCase("hello, java!"); // trueString str = "Hello, Java!";
// 长度
int length = str.length(); // 12
// 索引
char ch = str.charAt(0); // 'H'
// 子串
String substr = str.substring(7); // "Java!"
String substr2 = str.substring(7, 11); // "Java"
// 拼接
String newStr = str + " Welcome!"; // "Hello, Java! Welcome!"
// 查找
int index = str.indexOf("Java"); // 7
int lastIndex = str.lastIndexOf('a'); // 9
// 替换
String replaced = str.replace("Java", "World"); // "Hello, World!"
// 分割
String[] parts = str.split(", "); // ["Hello", "Java!"]
// 转换大小写
String upper = str.toUpperCase(); // "HELLO, JAVA!"
String lower = str.toLowerCase(); // "hello, java!"
// 去除空格
String trimStr = " Hello ".trim(); // "Hello"
// 比较
boolean equals = str.equals("Hello, Java!"); // true
boolean equalsIgnoreCase = str.equalsIgnoreCase("hello, java!"); // true10.2 StringBuffer 和 StringBuilder
StringBuffer:线程安全,效率较低StringBuilder:非线程安全,效率较高(推荐)
示例:
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(", ");
sb.append("Java!");
String result = sb.toString(); // "Hello, Java!"StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(", ");
sb.append("Java!");
String result = sb.toString(); // "Hello, Java!"11. 异常处理
11.1 什么是异常?
异常是程序运行时发生的错误,Java 使用异常机制来处理错误情况。
11.2 异常分类
- Checked Exception(受检异常):必须处理,如
IOException,SQLException - Unchecked Exception(非受检异常):可选处理,如
NullPointerException,ArrayIndexOutOfBoundsException - Error:严重错误,如
OutOfMemoryError,StackOverflowError
11.3 异常处理关键字
try:包含可能抛出异常的代码catch:捕获并处理异常finally:无论是否发生异常,都会执行throw:抛出异常throws:声明方法可能抛出的异常
11.4 异常处理示例
try {
// 可能抛出异常的代码
int[] arr = {1, 2, 3};
int num = arr[5]; // ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
// 处理异常
System.out.println("数组索引越界:" + e.getMessage());
} catch (Exception e) {
// 捕获其他异常
System.out.println("发生异常:" + e.getMessage());
} finally {
// 清理资源
System.out.println("finally 块执行");
}
// 抛出异常
public void checkAge(int age) throws IllegalArgumentException {
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数");
}
}try {
// 可能抛出异常的代码
int[] arr = {1, 2, 3};
int num = arr[5]; // ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
// 处理异常
System.out.println("数组索引越界:" + e.getMessage());
} catch (Exception e) {
// 捕获其他异常
System.out.println("发生异常:" + e.getMessage());
} finally {
// 清理资源
System.out.println("finally 块执行");
}
// 抛出异常
public void checkAge(int age) throws IllegalArgumentException {
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数");
}
}12. 包和导入
12.1 包的概念
包(Package)用于组织类和接口,避免命名冲突。
语法:
package com.example.java; // 包声明,必须在文件开头
public class MyClass {
// 类内容
}package com.example.java; // 包声明,必须在文件开头
public class MyClass {
// 类内容
}12.2 导入包
使用 import 关键字导入其他包的类。
语法:
import java.util.ArrayList; // 导入单个类
import java.util.*; // 导入包中的所有类
import static java.lang.Math.PI; // 导入静态常量
import static java.lang.Math.sqrt; // 导入静态方法
public class ImportExample {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
double circleArea = PI * 5 * 5;
double squareRoot = sqrt(16);
}
}import java.util.ArrayList; // 导入单个类
import java.util.*; // 导入包中的所有类
import static java.lang.Math.PI; // 导入静态常量
import static java.lang.Math.sqrt; // 导入静态方法
public class ImportExample {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
double circleArea = PI * 5 * 5;
double squareRoot = sqrt(16);
}
}13. 包装类与枚举(面试高频坑)
13.1 包装类与自动装箱拆箱
Java 为 8 种基本类型提供了对应的包装类:Integer、Long、Double、Float、Boolean、Byte、Short、Character。
自动装箱(Autoboxing): 基本类型 → 包装类 自动拆箱(Unboxing): 包装类 → 基本类型
Integer a = 100; // 自动装箱:Integer.valueOf(100)
int b = a; // 自动拆箱:a.intValue()Integer a = 100; // 自动装箱:Integer.valueOf(100)
int b = a; // 自动拆箱:a.intValue()Integer 缓存池(高频坑)
Integer.valueOf() 对 -128 ~ 127 范围内的值做了缓存,这个范围内返回的是同一个对象:
Integer a = 100; // Integer.valueOf(100) → 缓存池命中
Integer b = 100; // 同一个缓存对象
System.out.println(a == b); // true (同一个对象)
Integer c = 200; // Integer.valueOf(200) → 超出缓存范围,new Integer
Integer d = 200; // 另一个 new Integer
System.out.println(c == d); // false (不同对象)
System.out.println(c.equals(d)); // true (值相等)Integer a = 100; // Integer.valueOf(100) → 缓存池命中
Integer b = 100; // 同一个缓存对象
System.out.println(a == b); // true (同一个对象)
Integer c = 200; // Integer.valueOf(200) → 超出缓存范围,new Integer
Integer d = 200; // 另一个 new Integer
System.out.println(c == d); // false (不同对象)
System.out.println(c.equals(d)); // true (值相等)结论:包装类比较值必须用 equals(),禁止用 ==。
拆箱 NPE 陷阱
Integer x = null;
int y = x; // NullPointerException!自动拆箱调用 x.intValue()Integer x = null;
int y = x; // NullPointerException!自动拆箱调用 x.intValue()建议: 数据库字段、接口返回值如果可能为 null,用包装类接收,使用前判空。
13.2 枚举 Enum 实战场景
枚举不仅仅是常量集合,它可以有字段、方法、构造函数,Spring 中大量使用。
基础用法:替代常量
// 反例:用常量定义状态
public static final int ORDER_PENDING = 0;
public static final int ORDER_PAID = 1;
public static final int ORDER_SHIPPED = 2;
// 正例:用枚举
public enum OrderStatus {
PENDING, // 待支付
PAID, // 已支付
SHIPPED, // 已发货
CANCELLED // 已取消
}// 反例:用常量定义状态
public static final int ORDER_PENDING = 0;
public static final int ORDER_PAID = 1;
public static final int ORDER_SHIPPED = 2;
// 正例:用枚举
public enum OrderStatus {
PENDING, // 待支付
PAID, // 已支付
SHIPPED, // 已发货
CANCELLED // 已取消
}进阶:枚举 + 策略模式(替代 if-else)
public enum PaymentMethod {
ALIPAY("支付宝") {
@Override
public void pay(BigDecimal amount) {
System.out.println("调用支付宝接口,支付 " + amount);
}
},
WECHAT("微信支付") {
@Override
public void pay(BigDecimal amount) {
System.out.println("调用微信支付接口,支付 " + amount);
}
};
private final String desc;
PaymentMethod(String desc) { this.desc = desc; }
public abstract void pay(BigDecimal amount);
}
// 使用
PaymentMethod method = PaymentMethod.valueOf("ALIPAY");
method.pay(new BigDecimal("100.00"));public enum PaymentMethod {
ALIPAY("支付宝") {
@Override
public void pay(BigDecimal amount) {
System.out.println("调用支付宝接口,支付 " + amount);
}
},
WECHAT("微信支付") {
@Override
public void pay(BigDecimal amount) {
System.out.println("调用微信支付接口,支付 " + amount);
}
};
private final String desc;
PaymentMethod(String desc) { this.desc = desc; }
public abstract void pay(BigDecimal amount);
}
// 使用
PaymentMethod method = PaymentMethod.valueOf("ALIPAY");
method.pay(new BigDecimal("100.00"));枚举单例(最安全的单例实现)
public enum Singleton {
INSTANCE;
public void doSomething() {
System.out.println("枚举单例,天然防反射、防序列化破坏");
}
}
// 使用:Singleton.INSTANCE.doSomething();public enum Singleton {
INSTANCE;
public void doSomething() {
System.out.println("枚举单例,天然防反射、防序列化破坏");
}
}
// 使用:Singleton.INSTANCE.doSomething();14. 总结
Java 基础是学习 Java 编程的第一步,包括:
- Java 简介和开发环境搭建
- 基本语法、数据类型、变量和常量
- 运算符和控制流语句
- 面向对象编程(封装、继承、多态)
- 数组和字符串处理
- 异常处理
- 包和导入
掌握这些基础概念后,可以继续学习 Java 核心特性和高级特性,以及各种框架技术。
Cao Note