Java基础知识超详细总结(从入门到精通)

摘要: 本文系统梳理了Java编程语言的核心基础知识,涵盖语言特性、语法基础、数据类型、面向对象编程、常用API及异常处理等内容。文章结构清晰,代码示例丰富,适合Java初者系统学习,也适合开发者复习巩固。建议收藏,持续更新。


一、Java语言概述

1.1 什么是Java

Java是一种高级、面向对象、跨平台的编程语言,由Sun Microsystems公司于1995年推出,现由Oracle公司维护。Java的设计目标是"Write Once, Run Anywhere"(一次编写,到处运行),这一特性使其成为企业级应用开发的首选语言之一。

1.2 Java的核心特点

特性 说明
面向对象 支持封装、继承、多态,万物皆对象
跨平台性 通过JVM实现,编译后的字节码可在任何支持JVM的平台上运行
自动内存管理 垃圾回收机制(GC),无需手动释放内存
安全性 字节码验证、沙箱安全模型,防止恶意代码执行
多线程支持 内置多线程机制,提高程序并发性能
丰富的类库 提供大量标准API,涵盖IO、网络、集合、并发等
编译与解释并存 先编译为字节码,再由JVM解释执行(JIT优化后可达编译效率)

1.3 Java技术体系

复制代码
Java技术体系
├── Java SE(Standard Edition)标准版:桌面应用、基础核心
├── Java EE(Enterprise Edition)企业版:Web应用、分布式系统(现Jakarta EE)
└── Java ME(Micro Edition)微型版:嵌入式、移动设备开发

1.4 JDK、JRE、JVM的关系

复制代码
JDK(Java Development Kit)Java开发工具包
    ├── JRE(Java Runtime Environment)Java运行时环境
    │       └── JVM(Java Virtual Machine)Java虚拟机
    │       └── Java核心类库
    └── 开发工具(javac、java、javadoc等)

三者关系: JDK ⊃ JRE ⊃ JVM


二、Java程序基础

2.1 第一个Java程序

java 复制代码
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

程序解析:

  • public:访问修饰符,表示公共的
  • class:声明类的关键字
  • HelloWorld:类名,必须与文件名一致(HelloWorld.java)
  • static:静态修饰符,main方法必须声明为static
  • void:返回值类型,表示无返回值
  • main:程序入口方法,JVM从这里开始执行
  • String[] args:命令行参数数组
  • System.out.println():向控制台输出内容并换行

2.2 编译与运行流程

bash 复制代码
# 1. 编译:将.java源文件编译为.class字节码文件
javac HelloWorld.java

# 2. 运行:JVM加载并执行字节码
java HelloWorld

执行流程图:

复制代码
HelloWorld.java --(javac编译)--> HelloWorld.class --(java运行/JVM解释)--> 输出结果

2.3 注释规范

Java提供三种注释方式,良好的注释习惯是专业开发的必备素养:

java 复制代码
// 1. 单行注释:用于简短说明
int age = 20; // 用户年龄

/*
 * 2. 多行注释:用于较长说明
 * 这段代码用于计算用户年龄
 * 输入参数为出生年份
 */
int calculateAge(int birthYear) {
    return 2024 - birthYear;
}

/**
 * 3. 文档注释:用于生成API文档
 * 计算两个整数的和
 * @param a 第一个整数
 * @param b 第二个整数
 * @return 两数之和
 */
public int add(int a, int b) {
    return a + b;
}

三、Java语法基础

3.1 标识符与关键字

标识符命名规则:

  1. 由字母、数字、下划线_、美元符号$组成
  2. 不能以数字开头
  3. 不能使用Java关键字和保留字
  4. 区分大小写
  5. 建议使用有意义的名称(见名知意)

命名规范(阿里巴巴Java开发规范):

类型 规范 示例
类名 大驼峰(UpperCamelCase) UserInfoOrderService
方法名/变量名 小驼峰(lowerCamelCase) getUserNameuserAge
常量名 全大写,下划线分隔 MAX_VALUEPI
包名 全小写,点号分隔 com.company.project

Java关键字(48个):

类别 关键字
访问控制 privateprotectedpublic
类/方法/变量修饰 abstractclassextendsfinalimplementsinterfacenativenewstaticstrictfpsynchronizedtransientvolatile
程序控制 breakcasecontinuedefaultdoelseforifinstanceofreturnswitchwhile
错误处理 assertcatchfinallythrowthrowstry
包相关 importpackage
基本类型 booleanbytechardoublefloatintlongshort
变量引用 superthisvoid
保留字 gotoconst(尚未使用,但保留)

3.2 变量与常量

变量的本质: 变量是内存中的一块存储空间,用于存放数据。每个变量都有数据类型变量名三要素。

java 复制代码
// 变量声明的三种方式
// 方式1:声明并赋值
int age = 20;

// 方式2:先声明,后赋值
String name;
name = "张三";

// 方式3:同时声明多个同类型变量
int a = 1, b = 2, c = 3;

// 常量声明:使用final关键字
final double PI = 3.14159;
// PI = 3.14; // 编译错误!常量一旦赋值不可修改

成员变量 vs 局部变量:

特性 成员变量 局部变量
声明位置 类中,方法外 方法内或代码块内
作用域 整个类 当前方法或代码块
默认值 有(数值型为0,布尔型为false,引用型为null) 无,必须显式初始化
修饰符 可以使用访问修饰符 只能使用final
内存位置 堆内存(对象)或方法区(静态) 栈内存

四、数据类型详解

4.1 数据类型分类

Java是强类型语言,所有变量必须先声明类型。数据类型分为两大类:

复制代码
数据类型
├── 基本数据类型(Primitive Types)8种
│   ├── 整数类型:byte、short、int、long
│   ├── 浮点类型:float、double
│   ├── 字符类型:char
│   └── 布尔类型:boolean
└── 引用数据类型(Reference Types)3种
    ├── 类(Class):如String、自定义类
    ├── 接口(Interface)
    └── 数组(Array)

4.2 基本数据类型详解

类型 大小 默认值 取值范围 包装类 说明
byte 1字节(8位) 0 -128 ~ 127 Byte 节省空间,用于大型数组
short 2字节(16位) 0 -32768 ~ 32767 Short 兼容性保留,较少使用
int 4字节(32位) 0 -2³¹ ~ 2³¹-1 Integer 整数默认类型,最常用
long 8字节(64位) 0L -2⁶³ ~ 2⁶³-1 Long 大整数,后缀加L
float 4字节(32位) 0.0f IEEE 754标准 Float 单精度浮点,后缀加f
double 8字节(64位) 0.0d IEEE 754标准 Double 浮点默认类型,双精度
char 2字节(16位) '\u0000' 0 ~ 65535 Character Unicode字符
boolean 1位(JVM规范未明确规定) false true/false Boolean 逻辑判断

重要说明:

  • String不是基本数据类型,而是引用数据类型(类)
  • 整数字面量默认是int类型,超出范围需加L转为long
  • 浮点数字面量默认是double类型,赋值给float需加f或强制转换
java 复制代码
// 正确示例
int i = 100;
long l = 10000000000L; // 超出int范围,必须加L
float f = 3.14f;       // 必须加f,否则3.14默认是double
double d = 3.14159;

// 错误示例
// int big = 10000000000; // 编译错误:整数太大
// float f2 = 3.14;       // 编译错误:double不能自动转为float

4.3 类型转换

Java中类型转换分为自动类型转换(隐式)强制类型转换(显式)

自动类型转换(小范围 → 大范围):

复制代码
byte → short → int → long → float → double
        ↑
       char
java 复制代码
// 自动转换示例
byte b = 10;
int i = b;      // byte自动转为int
long l = i;     // int自动转为long
double d = l;   // long自动转为double

char c = 'A';
int charCode = c; // char自动转为int(ASCII码值65)

强制类型转换(大范围 → 小范围):

java 复制代码
// 强制转换语法:(目标类型)值
double d = 3.99;
int i = (int)d;  // i = 3,小数部分直接截断(非四舍五入)

int num = 130;
byte b = (byte)num; // b = -126,溢出导致数据失真

// 注意事项:强制转换可能导致精度丢失或数据溢出

类型转换注意事项:

  1. 布尔类型不能与其他类型转换
  2. 浮点型转整数型时,小数部分直接截断
  3. 大范围转小范围时,可能发生溢出(高位截断)
  4. 表达式中自动提升:byte/short/char参与运算时自动提升为int
java 复制代码
byte a = 10;
byte b = 20;
// byte c = a + b; // 编译错误!a+b自动提升为int
int c = a + b;      // 正确

五、运算符全解析

5.1 算术运算符

运算符 名称 示例 结果 说明
+ 加法/正号/字符串连接 5 + 3 8 字符串连接:"a" + 1"a1"
- 减法/负号 5 - 3 2
* 乘法 5 * 3 15
/ 除法 5 / 2 2 整数相除结果取整
% 取模(求余) 5 % 2 1 结果符号与被除数相同
++ 自增 ++a / a++ 前缀先增后用,后缀先用后增
-- 自减 --a / a-- 前缀先减后用,后缀先用后减
java 复制代码
// 自增自减详解
int a = 5;
int b = ++a; // a先变为6,再赋值给b。结果:a=6, b=6

int c = 5;
int d = c++; // 先将c=5赋值给d,c再变为6。结果:c=6, d=5

// 除法陷阱
int x = 5 / 2;      // x = 2(整数除法截断小数)
double y = 5 / 2;   // y = 2.0(先整数除法得2,再转double)
double z = 5.0 / 2; // z = 2.5(浮点运算)

5.2 赋值运算符

运算符 示例 等价于 说明
= a = 5 基本赋值
+= a += 3 a = a + 3 加法赋值
-= a -= 3 a = a - 3 减法赋值
*= a *= 3 a = a * 3 乘法赋值
/= a /= 3 a = a / 3 除法赋值
%= a %= 3 a = a % 3 取模赋值

复合赋值运算符的隐式类型转换:

java 复制代码
byte b = 10;
// b = b + 5;    // 编译错误!b+5结果为int
b += 5;          // 正确!复合赋值运算符自动强制转换
// 等价于:b = (byte)(b + 5);

5.3 比较运算符

运算符 名称 示例 结果
== 等于 5 == 5 true
!= 不等于 5 != 3 true
> 大于 5 > 3 true
< 小于 5 < 3 false
>= 大于等于 5 >= 5 true
<= 小于等于 5 <= 3 false

⚠️ 重要区别:== vs equals()

java 复制代码
// 基本数据类型:==比较的是值
int a = 10, b = 10;
System.out.println(a == b); // true

// 引用数据类型:==比较的是内存地址(引用)
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2);     // false(不同对象,地址不同)
System.out.println(s1.equals(s2)); // true(内容相同)

// 字符串常量池特例
String s3 = "hello";
String s4 = "hello";
System.out.println(s3 == s4); // true(常量池复用)

5.4 逻辑运算符

运算符 名称 示例 说明
& 逻辑与 A & B 两边都true才true,两边都执行
` ` 逻辑或 `A
! 逻辑非 !A 取反
^ 逻辑异或 A ^ B 两边不同为true,相同为false
&& 短路与 A && B 左边false右边不执行
` ` 短路或

短路特性详解(开发中推荐使用&&||):

java 复制代码
int a = 5, b = 0;

// 短路或:左边为true,右边不执行(不会报除零错误)
if (a > 0 || (b / 0 > 0)) {
    System.out.println("短路或:右边未执行");
}

// 非短路或:两边都执行(会报ArithmeticException)
// if (a > 0 | (b / 0 > 0)) { } // 运行时错误!

// 经典应用:防止空指针异常
String str = null;
if (str != null && str.length() > 0) { // 安全!str为null时不会调用length()
    System.out.println("字符串非空");
}

5.5 位运算符(了解)

运算符 名称 示例 说明
& 按位与 5 & 3 对应位都为1才为1
` ` 按位或 `5
^ 按位异或 5 ^ 3 对应位不同为1
~ 按位取反 ~5 0变1,1变0
<< 左移 5 << 2 左移n位,相当于乘以2ⁿ
>> 右移 5 >> 2 右移n位,相当于除以2ⁿ(带符号)
>>> 无符号右移 5 >>> 2 高位补0
java 复制代码
// 位运算经典应用:交换两个数(无需临时变量)
int a = 5, b = 3;
a = a ^ b;
b = a ^ b; // b = (a^b)^b = a
a = a ^ b; // a = (a^b)^a = b
System.out.println("a=" + a + ", b=" + b); // a=3, b=5

// 高效判断奇偶(位运算比取模快)
int num = 7;
if ((num & 1) == 1) {
    System.out.println(num + "是奇数");
}

5.6 三元运算符

java 复制代码
// 语法:条件表达式 ? 表达式1 : 表达式2
// 条件为true返回表达式1,否则返回表达式2

int a = 10, b = 20;
int max = (a > b) ? a : b; // max = 20

// 嵌套三元运算符(不建议过多嵌套,可读性差)
int score = 85;
String grade = (score >= 90) ? "A" : (score >= 80) ? "B" : (score >= 60) ? "C" : "D";

5.7 运算符优先级

优先级 运算符 结合性
1 ()[]· 从左到右
2 !~++--+(正)、-(负) 从右到左
3 */% 从左到右
4 +- 从左到右
5 <<>>>>> 从左到右
6 <<=>>=instanceof 从左到右
7 ==!= 从左到右
8 & 从左到右
9 ^ 从左到右
10 ` `
11 && 从左到右
12 `
13 ?: 从右到左
14 =+=-=*=/=%= 从右到左

建议: 不确定优先级时,使用括号()明确运算顺序,提高代码可读性。


六、流程控制语句

6.1 选择结构

6.1.1 if-else语句
java 复制代码
// 单分支
if (条件) {
    // 条件为true时执行
}

// 双分支
if (条件) {
    // 条件为true时执行
} else {
    // 条件为false时执行
}

// 多分支
if (条件1) {
    // 条件1为true
} else if (条件2) {
    // 条件2为true
} else if (条件3) {
    // 条件3为true
} else {
    // 以上都不满足
}

// 嵌套if
if (外层条件) {
    if (内层条件) {
        // 两层都满足
    }
}

实际应用示例:

java 复制代码
// 根据成绩评定等级
int score = 85;
if (score < 0 || score > 100) {
    System.out.println("成绩输入有误");
} else if (score >= 90) {
    System.out.println("优秀");
} else if (score >= 80) {
    System.out.println("良好");
} else if (score >= 70) {
    System.out.println("中等");
} else if (score >= 60) {
    System.out.println("及格");
} else {
    System.out.println("不及格");
}
6.1.2 switch语句
java 复制代码
// 传统语法(Java 12之前)
switch (表达式) {
    case 常量1:
        // 语句
        break; // 必须有break,否则穿透执行
    case 常量2:
        // 语句
        break;
    default:
        // 默认语句
        break;
}

// 增强语法(Java 12+):箭头语法,自动break
switch (表达式) {
    case 常量1 -> // 单条语句;
    case 常量2 -> {
        // 多条语句
    }
    default -> // 默认处理;
}

switch表达式类型限制: JDK 5之前只能是byteshortcharint;JDK 5加入枚举;JDK 7加入String

java 复制代码
// 示例:根据月份判断季节(Java 14+ switch表达式)
String season = switch (month) {
    case 3, 4, 5 -> "春季";
    case 6, 7, 8 -> "夏季";
    case 9, 10, 11 -> "秋季";
    case 12, 1, 2 -> "冬季";
    default -> "未知";
};

6.2 循环结构

6.2.1 for循环
java 复制代码
// 标准for循环
for (初始化; 条件判断; 迭代操作) {
    // 循环体
}

// 示例:计算1~100的和
int sum = 0;
for (int i = 1; i <= 100; i++) {
    sum += i;
}

// 增强for循环(foreach):用于遍历数组或集合
int[] arr = {1, 2, 3, 4, 5};
for (int num : arr) {
    System.out.println(num);
}
6.2.2 while循环
java 复制代码
// 先判断,后执行(可能一次都不执行)
while (条件) {
    // 循环体
}

// 示例:猜数字游戏
int target = 50;
int guess;
Scanner scanner = new Scanner(System.in);
while ((guess = scanner.nextInt()) != target) {
    System.out.println(guess > target ? "太大了" : "太小了");
}
System.out.println("猜对了!");
6.2.3 do-while循环
java 复制代码
// 先执行,后判断(至少执行一次)
do {
    // 循环体
} while (条件);

// 示例:菜单选择(至少显示一次)
int choice;
do {
    System.out.println("1. 查询 2. 添加 3. 退出");
    choice = scanner.nextInt();
    // 处理选择...
} while (choice != 3);

三种循环对比:

循环类型 适用场景 特点
for 已知循环次数 结构紧凑,计数器作用域在循环内
while 未知循环次数,可能不执行 先判断后执行
do-while 至少执行一次 先执行后判断

6.3 跳转语句

语句 作用 使用场景
break 跳出当前循环或switch 结束循环、跳出case
continue 跳过本次循环,进入下一次 过滤某些情况
return 结束方法,返回结果 方法退出
label(标签) 标识循环,配合break/continue使用 跳出多层循环
java 复制代码
// break跳出多层循环
outer: for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
        if (i * j > 50) {
            break outer; // 跳出外层循环
        }
    }
}

// continue跳过本次
for (int i = 1; i <= 10; i++) {
    if (i % 2 == 0) {
        continue; // 跳过偶数,只打印奇数
    }
    System.out.println(i);
}

七、数组

7.1 数组概述

数组是相同数据类型元素的集合,属于引用数据类型。数组一旦创建,长度不可改变。

7.2 数组声明与初始化

java 复制代码
// 方式1:声明并分配空间(动态初始化)
int[] arr1 = new int[5]; // 5个元素,默认值0

// 方式2:声明并赋值(静态初始化)
int[] arr2 = new int[]{1, 2, 3, 4, 5};
// 简写形式
int[] arr3 = {1, 2, 3, 4, 5};

// 方式3:先声明,后创建
int[] arr4;
arr4 = new int[10];

// 注意:以下写法错误
// int[] arr = new int[5]{1,2,3,4,5}; // 编译错误!不能同时指定长度和元素

7.3 数组操作

java 复制代码
int[] arr = {10, 20, 30, 40, 50};

// 访问元素(索引从0开始)
int first = arr[0];   // 10
int last = arr[4];    // 50
// arr[5]; // ArrayIndexOutOfBoundsException!数组越界

// 获取长度
int len = arr.length; // 5(注意不是方法,是属性)

// 遍历数组
// 方式1:for循环
for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
}

// 方式2:增强for循环
for (int num : arr) {
    System.out.println(num);
}

// 方式3:Arrays工具类
System.out.println(Arrays.toString(arr)); // [10, 20, 30, 40, 50]

// 排序
Arrays.sort(arr); // 快速排序/归并排序(Dual-Pivot Quicksort)

// 查找(先排序后二分查找)
int index = Arrays.binarySearch(arr, 30); // 返回索引,不存在返回负数

// 填充
Arrays.fill(arr, 0); // 所有元素置为0

// 复制
int[] copy = Arrays.copyOf(arr, arr.length); // 完整复制
int[] part = Arrays.copyOfRange(arr, 1, 4); // 复制索引[1,4)的元素

7.4 二维数组

java 复制代码
// 声明与初始化
int[][] matrix = new int[3][4]; // 3行4列
int[][] matrix2 = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

// 不规则数组(每行长度不同)
int[][] jagged = new int[3][];
jagged[0] = new int[2];
jagged[1] = new int[4];
jagged[2] = new int[3];

// 遍历二维数组
for (int i = 0; i < matrix2.length; i++) {       // 行
    for (int j = 0; j < matrix2[i].length; j++) { // 列
        System.out.print(matrix2[i][j] + " ");
    }
    System.out.println();
}

八、面向对象编程(OOP)

面向对象编程是Java的核心思想,三大特性:封装、继承、多态

8.1 类与对象

类(Class): 对一类事物的抽象描述,是创建对象的模板。
对象(Object): 类的实例,是客观存在的具体个体。

java 复制代码
// 定义类
public class Student {
    // 成员变量(属性)
    private String name;    // 姓名
    private int age;        // 年龄
    private String studentId; // 学号
    
    // 构造方法(Constructor)
    public Student() {} // 无参构造
    
    public Student(String name, int age, String studentId) {
        this.name = name;
        this.age = age;
        this.studentId = studentId;
    }
    
    // 成员方法(行为)
    public void study() {
        System.out.println(name + "正在学习Java...");
    }
    
    // Getter和Setter方法(封装的体现)
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    // ...其他getter/setter
}

// 创建对象
Student stu = new Student("张三", 20, "2024001");
stu.study(); // 调用方法

8.2 构造方法详解

java 复制代码
public class Person {
    private String name;
    private int age;
    
    // 无参构造(默认提供,一旦显式定义有参构造,默认不再提供)
    public Person() {
        System.out.println("无参构造被调用");
    }
    
    // 有参构造
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // 构造方法重载
    public Person(String name) {
        this(name, 0); // 调用同类其他构造(必须放在第一行)
    }
    
    // this()和super()不能同时出现在一个构造方法中
}

构造方法特点:

  1. 方法名与类名相同
  2. 没有返回值类型(连void都没有)
  3. 可以重载
  4. 不能递归调用

8.3 三大特性之------封装(Encapsulation)

封装的目的: 隐藏对象的内部实现细节,仅对外暴露有限的访问接口,保证数据安全性。

java 复制代码
public class BankAccount {
    // 1. 成员变量私有化(private)
    private String accountNo;   // 账号
    private double balance;     // 余额(敏感数据)
    private String password;    // 密码
    
    // 2. 提供公共的getter/setter方法
    public double getBalance() {
        return balance; // 只允许查看余额
    }
    
    // 3. 对敏感操作进行控制
    public void withdraw(double amount, String pwd) {
        // 验证密码
        if (!this.password.equals(pwd)) {
            System.out.println("密码错误");
            return;
        }
        // 验证余额
        if (amount > balance) {
            System.out.println("余额不足");
            return;
        }
        // 执行取款
        this.balance -= amount;
        System.out.println("取款成功,余额:" + balance);
    }
    
    // 4. 不提供直接修改余额的方法(防止随意篡改)
    // 没有setBalance()方法!
}

封装的好处:

  • 提高安全性:防止外部随意修改内部数据
  • 提高灵活性:内部实现可以改变,不影响外部调用
  • 提高可维护性:结构清晰,便于调试和修改
  • 提高复用性:封装好的类可以在多个项目中使用

8.4 三大特性之------继承(Inheritance)

继承的本质: 子类继承父类的属性和方法,实现代码复用,并可以扩展新功能。

java 复制代码
// 父类
public class Animal {
    protected String name; // protected:子类可访问
    protected int age;
    
    public void eat() {
        System.out.println(name + "在吃东西");
    }
    
    public void sleep() {
        System.out.println(name + "在睡觉");
    }
}

// 子类
public class Dog extends Animal { // extends关键字继承
    private String breed; // 品种(子类特有属性)
    
    // 构造方法
    public Dog(String name, int age, String breed) {
        this.name = name; // 继承自父类
        this.age = age;
        this.breed = breed;
    }
    
    // 子类特有方法
    public void bark() {
        System.out.println(name + ":汪汪汪!");
    }
    
    // 方法重写(Override)
    @Override
    public void eat() {
        System.out.println(name + "在吃骨头"); // 子类自定义行为
    }
}

// 使用
Dog dog = new Dog("旺财", 3, "金毛");
dog.eat();   // 调用重写后的方法:旺财在吃骨头
dog.sleep(); // 调用继承的方法:旺财在睡觉
dog.bark();  // 调用子类特有方法:旺财:汪汪汪!

继承的重要规则:

  1. Java只支持单继承(一个类只能有一个直接父类)
  2. 子类继承父类所有非私有成员
  3. 子类不能继承父类的构造方法 (但可以通过super()调用)
  4. 可以使用super关键字访问父类成员
  5. 继承关系要符合"is-a"原则(狗是动物)

方法重写(Override)规则:

  • 方法名、参数列表、返回值类型必须相同
  • 访问权限不能比父类更严格(可以相同或更宽松)
  • 抛出的异常不能比父类更宽泛
  • 使用@Override注解进行校验

8.5 三大特性之------多态(Polymorphism)

多态的前提: 继承 + 方法重写 + 向上转型

多态的体现: 父类引用指向子类对象,调用方法时执行子类重写的方法。

java 复制代码
// 父类引用指向子类对象(向上转型)
Animal animal = new Dog("旺财", 3, "金毛");
animal.eat(); // 实际执行Dog的eat()方法:旺财在吃骨头

// 多态数组
Animal[] animals = new Animal[3];
animals[0] = new Dog("旺财", 3, "金毛");
animals[1] = new Cat("咪咪", 2, "橘猫");
animals[2] = new Bird("小白", 1, "鹦鹉");

// 统一遍历,不同表现
for (Animal a : animals) {
    a.eat(); // 每个对象执行各自重写的方法
}

// 向下转型(需谨慎,可能ClassCastException)
if (animal instanceof Dog) { // 先判断类型
    Dog dog = (Dog) animal; // 安全转型
    dog.bark();
}

多态的好处:

  • 可扩展性: 新增子类不影响原有代码
  • 可替换性: 子类对象可以随时替换父类对象
  • 接口性: 通过父类引用操作不同子类对象
  • 灵活性: 简化代码,提高复用

8.6 关键字详解

8.6.1 this关键字

this代表当前对象的引用。

java 复制代码
public class ThisDemo {
    private int num;
    
    // 1. 区分成员变量和局部变量
    public void setNum(int num) {
        this.num = num; // this.num是成员变量,num是参数
    }
    
    // 2. 调用当前类的其他构造方法
    public ThisDemo() {
        this(0); // 调用有参构造,必须放在第一行
    }
    
    public ThisDemo(int num) {
        this.num = num;
    }
    
    // 3. 返回当前对象(链式调用)
    public ThisDemo increment() {
        num++;
        return this;
    }
}
8.6.2 super关键字

super代表父类对象的引用。

java 复制代码
public class SuperDemo extends Parent {
    private int value;
    
    public SuperDemo(int value, int parentValue) {
        super(parentValue); // 调用父类构造,必须放在第一行
        this.value = value;
    }
    
    public void show() {
        System.out.println(super.value); // 访问父类成员
        super.display(); // 调用父类方法
    }
}
8.6.3 static关键字

static修饰的成员属于,而非某个对象。

java 复制代码
public class StaticDemo {
    // 静态变量(类变量):所有对象共享一份
    public static int count = 0;
    
    // 实例变量:每个对象独立一份
    private int id;
    
    // 静态代码块:类加载时执行,只执行一次
    static {
        System.out.println("静态代码块执行");
        count = 100;
    }
    
    // 实例代码块:每次创建对象时执行
    {
        System.out.println("实例代码块执行");
        id = ++count;
    }
    
    // 静态方法:属于类,可直接通过类名调用
    public static void showCount() {
        System.out.println("当前count:" + count);
        // System.out.println(id); // 错误!静态方法不能访问非静态成员
    }
    
    // 静态内部类
    public static class Inner {
        public void test() {
            System.out.println(count); // 可以访问外部静态成员
        }
    }
}

// 使用
StaticDemo.showCount(); // 类名.静态方法
StaticDemo.Inner inner = new StaticDemo.Inner(); // 直接创建,不依赖外部对象

静态成员加载顺序: 静态变量/代码块按代码顺序加载 → main方法 → 实例变量/代码块 → 构造方法

8.6.4 final关键字

final表示"最终的、不可改变的"。

修饰目标 作用
该类不能被继承(如StringMath
方法 该方法不能被重写
变量 变量只能赋值一次,成为常量
java 复制代码
// final类
public final class FinalClass {
    // 不能被继承
}

// final方法
public class Parent {
    public final void finalMethod() {
        // 子类不能重写
    }
}

// final变量
public class FinalVar {
    // 1. 成员常量:声明时或构造方法中初始化
    private final int MAX_SIZE = 100;
    
    // 2. 静态常量:声明时或静态代码块中初始化
    public static final double PI = 3.14159;
    
    // 3. 引用类型常量:引用不可变,但对象内容可变
    private final StringBuilder sb = new StringBuilder("Hello");
    
    public void modify() {
        // sb = new StringBuilder(); // 错误!不能改变引用
        sb.append(" World"); // 正确!可以修改对象内容
    }
}

8.7 访问修饰符

修饰符 同类 同包 子类 任何地方
private
default(缺省) ✗(不同包)
protected
public

使用原则: 尽量私有化,按需开放。


九、抽象类与接口

9.1 抽象类(Abstract Class)

抽象类是不能被实例化的类,用于定义子类的通用模板。

java 复制代码
// 抽象类
public abstract class Shape {
    // 可以有成员变量
    protected String color;
    
    // 可以有构造方法(供子类调用)
    public Shape(String color) {
        this.color = color;
    }
    
    // 可以有普通方法
    public void showColor() {
        System.out.println("颜色:" + color);
    }
    
    // 抽象方法:没有方法体,子类必须实现
    public abstract double getArea();
    public abstract double getPerimeter();
}

// 具体子类
public class Circle extends Shape {
    private double radius;
    
    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }
    
    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public double getPerimeter() {
        return 2 * Math.PI * radius;
    }
}

抽象类特点:

  1. 使用abstract关键字修饰
  2. 可以包含抽象方法和普通方法
  3. 可以有成员变量和构造方法
  4. 子类必须实现所有抽象方法(除非子类也是抽象类)
  5. 不能创建对象,但可以声明引用变量

9.2 接口(Interface)

接口是更纯粹的抽象,JDK 8之前只能包含常量和抽象方法;JDK 8+支持默认方法和静态方法;JDK 9+支持私有方法。

java 复制代码
// 接口定义
public interface Flyable {
    // 隐式:public static final
    int MAX_HEIGHT = 10000;
    
    // 抽象方法(JDK 7及以前唯一形式)
    void fly();
    
    // 默认方法(JDK 8+):有方法体,子类可选择性重写
    default void land() {
        System.out.println("安全着陆");
    }
    
    // 静态方法(JDK 8+):属于接口,通过接口名调用
    static void checkEngine() {
        System.out.println("检查引擎状态");
    }
    
    // 私有方法(JDK 9+):接口内部复用
    private void log(String msg) {
        System.out.println("[LOG] " + msg);
    }
}

// 实现接口
public class Bird implements Flyable {
    @Override
    public void fly() {
        System.out.println("用翅膀飞行");
    }
    
    // 可以选择重写默认方法
    @Override
    public void land() {
        System.out.println("Bird:轻盈着陆");
    }
}

// 一个类可以实现多个接口
public class Superman implements Flyable, Runnable, Fightable {
    // 必须实现所有抽象方法
}

接口与抽象类的区别:

特性 抽象类 接口
继承/实现 单继承(extends) 多实现(implements)
构造方法
成员变量 可以有各种类型 只能是public static final常量
方法 抽象+普通 JDK8前只能抽象;JDK8+可有默认/静态方法
设计目的 "is-a"关系,代码复用 "has-a"能力,定义规范
使用场景 共性提取 能力定义

十、常用类与API

10.1 String类(重点)

String是不可变字符序列,所有修改操作都会创建新对象。

java 复制代码
// 创建方式
String s1 = "hello";              // 常量池
String s2 = new String("hello");    // 堆内存
String s3 = "hello";              // 常量池复用

System.out.println(s1 == s2);     // false(地址不同)
System.out.println(s1 == s3);     // true(常量池复用)
System.out.println(s1.equals(s2)); // true(内容相同)

// 常用方法
String str = "  Hello World  ";
str.length();           // 13
str.trim();             // "Hello World"(去首尾空格)
str.toLowerCase();      // "  hello world  "
str.toUpperCase();      // "  HELLO WORLD  "
str.substring(2, 7);     // "Hello"(含头不含尾)
str.indexOf("World");   // 8
str.replace("World", "Java"); // "  Hello Java  "
str.split(" ");         // 按空格分割为数组
str.contains("Hello");  // true
str.startsWith("  H");  // true
str.charAt(2);          // 'H'

// StringBuilder/StringBuffer:可变字符串
// StringBuilder:线程不安全,效率高(单线程推荐)
// StringBuffer:线程安全,效率略低(多线程推荐)
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");      // Hello World
sb.insert(5, ",");      // Hello, World
sb.delete(5, 6);        // Hello World
sb.reverse();           // dlroW olleH

String不可变性的好处:

  1. 字符串常量池的实现基础,节省内存
  2. 多线程安全,无需同步
  3. 适合作为Map的键(hashCode不变)
  4. 防止恶意修改(如网络连接参数)

10.2 包装类

基本数据类型与对应包装类:

基本类型 包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
java 复制代码
// 装箱:基本类型 → 包装类
Integer i1 = Integer.valueOf(100); // 手动装箱
Integer i2 = 100;                  // 自动装箱(JDK 5+)

// 拆箱:包装类 → 基本类型
int num1 = i1.intValue(); // 手动拆箱
int num2 = i2;            // 自动拆箱

// 包装类常用方法
Integer.parseInt("123");      // 字符串转int
Integer.toString(123);        // int转字符串
Integer.MAX_VALUE;            // 最大值
Integer.MIN_VALUE;            // 最小值

// 注意:缓存机制(-128 ~ 127)
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true(缓存复用)

Integer c = 200;
Integer d = 200;
System.out.println(c == d); // false(超出缓存,新建对象)

10.3 Math类

java 复制代码
Math.abs(-10);        // 10(绝对值)
Math.max(10, 20);     // 20(最大值)
Math.min(10, 20);     // 10(最小值)
Math.ceil(3.14);      // 4.0(向上取整)
Math.floor(3.14);     // 3.0(向下取整)
Math.round(3.14);     // 3(四舍五入)
Math.pow(2, 3);       // 8.0(2的3次方)
Math.sqrt(16);        // 4.0(平方根)
Math.random();        // [0.0, 1.0)随机数
// 生成[1, 100]随机整数
int random = (int)(Math.random() * 100) + 1;

10.4 日期时间类(JDK 8新API推荐)

java 复制代码
// JDK 8之前(不推荐,线程不安全,设计混乱)
Date date = new Date();
Calendar calendar = Calendar.getInstance();

// JDK 8+ 新日期时间API(java.time包,推荐)
import java.time.*;
import java.time.format.DateTimeFormatter;

// 当前日期
LocalDate today = LocalDate.now(); // 2024-05-11
LocalTime now = LocalTime.now();   // 14:30:25.123
LocalDateTime dateTime = LocalDateTime.now();

// 指定日期
LocalDate birth = LocalDate.of(2000, 1, 1);

// 日期计算
LocalDate nextWeek = today.plusWeeks(1);
LocalDate lastMonth = today.minusMonths(1);

// 格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String str = dateTime.format(formatter);

// 解析
LocalDate parsed = LocalDate.parse("2024-05-11");

十一、异常处理

11.1 异常体系

复制代码
Throwable(所有异常的根类)
├── Error(错误):严重问题,程序无法处理
│   ├── OutOfMemoryError(内存溢出)
│   ├── StackOverflowError(栈溢出)
│   └── ...
└── Exception(异常):可以处理的问题
    ├── RuntimeException(运行时异常/非受检异常)
    │   ├── NullPointerException(空指针)
    │   ├── ArrayIndexOutOfBoundsException(数组越界)
    │   ├── ClassCastException(类型转换异常)
    │   ├── ArithmeticException(算术异常,如除零)
    │   └── ...
    └── 其他Exception(编译时异常/受检异常)
        ├── IOException
        ├── SQLException
        ├── ClassNotFoundException
        └── ...

11.2 异常处理机制

java 复制代码
// 基本语法
try {
    // 可能抛出异常的代码
    int result = 10 / 0;
} catch (ArithmeticException e) {
    // 捕获并处理特定异常
    System.out.println("除数不能为0:" + e.getMessage());
} catch (Exception e) {
    // 捕获其他异常(子类在前,父类在后)
    System.out.println("发生异常:" + e.getMessage());
} finally {
    // 无论是否异常,最终都会执行
    System.out.println("清理资源...");
}

// 多异常合并(JDK 7+)
catch (IOException | SQLException e) {
    // 处理多种异常
}

// try-with-resources(自动关闭资源,JDK 7+)
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
    String line = br.readLine();
} catch (IOException e) {
    e.printStackTrace();
}
// br会自动关闭,无需finally中手动关闭

// 抛出异常
public void method() throws IOException, SQLException {
    // 方法声明可能抛出的异常
    if (error) {
        throw new IOException("文件读取失败");
    }
}

// 自定义异常
public class BusinessException extends RuntimeException {
    private int code;
    
    public BusinessException(int code, String message) {
        super(message);
        this.code = code;
    }
    
    public int getCode() {
        return code;
    }
}

异常处理原则:

  1. 不要捕获Throwable或Exception,应捕获具体异常
  2. 不要吞掉异常,至少打印日志
  3. 不要在finally中return,会覆盖try中的return
  4. 优先使用标准异常,自定义异常用于业务场景
  5. 异常信息要具体,便于定位问题

十二、总结与学习建议

12.1 知识图谱

复制代码
Java基础知识
├── 语言基础
│   ├── 数据类型(8种基本 + 引用)
│   ├── 运算符(算术、比较、逻辑、位运算)
│   └── 流程控制(if、switch、for、while)
├── 数组
│   ├── 一维数组
│   └── 二维数组
├── 面向对象
│   ├── 类与对象
│   ├── 三大特性(封装、继承、多态)
│   ├── 关键字(this、super、static、final)
│   ├── 抽象类与接口
│   └── 访问控制
├── 常用API
│   ├── String/StringBuilder
│   ├── 包装类
│   ├── Math
│   └── 日期时间
└── 异常处理
    ├── 异常体系
    └── try-catch-finally

12.2 学习建议

  1. 多敲代码:编程是实践学科,看十遍不如写一遍
  2. 理解原理:不要死记API,理解底层机制(如String不可变性)
  3. 阅读源码:从JDK源码中学习优秀的设计(如ArrayList、HashMap)
  4. 做项目:通过实际项目巩固知识,发现问题
  5. 持续更新:Java版本迭代快,关注新特性(如Record、Pattern Matching)

12.3 推荐学习资源

  • 官方文档: Oracle Java Documentation
  • 经典书籍: 《Java核心技术》、《Effective Java》、《深入理解Java虚拟机》
  • 在线平台: CSDN、掘金、Stack Overflow

结语: Java基础知识是构建高楼大厦的地基,只有地基牢固,才能在框架学习、分布式系统、微服务架构等高级领域游刃有余。本文涵盖了Java基础的核心知识点,建议结合实践反复巩固。如有错误或不足,欢迎在评论区指正交流!


如果觉得本文对你有帮助,欢迎点赞、收藏、转发! 您的支持是我持续更新的动力!

相关推荐
咖啡八杯1 小时前
GoF设计模式——抽象工厂模式
java·后端·spring·设计模式·抽象工厂模式
Thanks_ks1 小时前
分布式锁:Redis 与 Redisson 的工程实践与避坑指南
java·redis·分布式锁·redisson·微服务架构·并发编程·高可用
掉鱼的猫1 小时前
agentscope-harness vs solon-ai-harness:Java 智能体「马具引擎」的双雄对决
java·openai
RainCity1 小时前
Java Swing 自定义组件库分享(四)
java·笔记·后端
带刺的坐椅1 小时前
agentscope-harness vs solon-ai-harness:Java 智能体「马具引擎」的双雄对决
java·ai·llm·solon·agentscope·harness
Seven971 小时前
Paxos算法:如何解决分布式系统中的共识问题?
java
铁皮哥2 小时前
【力扣题解】LeetCode 25. K 个一组翻转链表
java·数据结构·windows·python·算法·leetcode·链表
小新同学^O^2 小时前
简单学习 --> 单例模式
java·学习·多线程
Henray20242 小时前
LRU缓存设计与实现
java·面试