Java 基础知识总结(超详细整理)
Java基础知识总结(超详细整理)
Java是一种跨平台、面向对象的编程语言,其设计理念为“一次编写,到处运行”(Write Once, Run Anywhere),广泛应用于后端开发、Android开发、大数据处理等领域。以下从核心概念、语法、进阶特性等维度,系统梳理Java基础知识。
一、Java语言核心概念
1.1 跨平台原理
Java的跨平台依赖JVM(Java Virtual Machine,Java虚拟机) :
- 开发者编写的
.java源文件,通过javac编译器编译为字节码文件(.class) ; - 不同操作系统(Windows、Linux、macOS)安装对应的JVM,JVM负责将字节码解析为本地机器指令并执行;
- 注意:JVM是跨平台的核心,但JVM本身不跨平台(需为不同系统安装对应版本的JVM)。
1.2 JDK、JRE、JVM的关系
三者是Java开发和运行的基础,关系如下(包含关系:JDK > JRE > JVM):
| 组件 | 全称 | 作用 |
|---|---|---|
| JVM | Java Virtual Machine | 执行字节码,是跨平台的核心 |
| JRE | Java Runtime Environment | Java运行环境,包含JVM + 核心类库(如java.lang包),供程序运行使用 |
| JDK | Java Development Kit | Java开发工具包,包含JRE + 编译工具(javac)、调试工具(jdb)等,供开发使用 |
1.3 面向对象三大特性
Java是纯面向对象语言(除基本数据类型外,万物皆对象),核心特性为:
- 封装:隐藏对象的属性和实现细节,仅通过公共方法(
public)对外暴露接口,提高安全性和可维护性。
例:用private修饰成员变量,通过getter/setter方法访问和修改。 - 继承:子类(Subclass)继承父类(Superclass)的非私有属性和方法,实现代码复用;Java仅支持单继承(一个子类只能有一个直接父类),但可通过接口实现多继承效果。
关键字:extends(继承类)、super(调用父类构造器/方法)。 - 多态:同一行为在不同对象上表现出不同形态,分为“编译时多态”(方法重载)和“运行时多态”(方法重写)。
条件:子类重写父类方法、父类引用指向子类对象(如Animal dog = new Dog();)。
二、Java语法基础
2.1 数据类型
Java数据类型分为基本数据类型和引用数据类型,二者在内存存储、传递方式上有本质区别。
2.1.1 基本数据类型(8种)
存储“值”本身,直接分配在栈内存中,默认值非null:
| 类型 | 占用字节 | 取值范围 | 默认值 | 示例 |
|---|---|---|---|---|
| byte(字节) | 1 | -128 ~ 127 | 0 | byte age = 20; |
| short(短整) | 2 | -32768 ~ 32767 | 0 | short score = 95; |
| int(整数) | 4 | -2³¹ ~ 2³¹-1(约-21亿 ~ 21亿) | 0 | int num = 100; |
| long(长整) | 8 | -2⁶³ ~ 2⁶³-1 | 0L | long id = 123456L; |
| float(单精) | 4 | 约±3.4×10³⁸(精度6-7位小数) | 0.0F | float pi = 3.14F; |
| double(双精) | 8 | 约±1.8×10³⁰⁸(精度15-16位小数) | 0.0D | double price = 9.9; |
| char(字符) | 2 | 0 ~ 65535(Unicode字符,如’a’、‘中’) | ‘\u0000’ | char c = 'A'; |
| boolean(布尔) | 1/4 | true(真)、false(假) | false | boolean flag = true; |
2.1.2 引用数据类型
存储“对象的内存地址”,对象本身在堆内存中,默认值为null,主要包括:
- 类(Class):如
String、自定义类(Person); - 接口(Interface):如
List、Runnable; - 数组(Array):如
int[] arr、String[] strs。
2.1.3 类型转换
- 自动类型转换:小范围类型 → 大范围类型(安全,无需手动处理)。
例:int a = 10; long b = a;(int→long)、float f = 3.14; double d = f;(float→double)。 - 强制类型转换:大范围类型 → 小范围类型(可能丢失精度,需加
()指定目标类型)。
例:long x = 100L; int y = (int)x;(安全)、double m = 3.14; int n = (int)m;(n=3,丢失小数)。
2.2 变量与常量
2.2.1 变量
- 定义格式:
数据类型 变量名 = 初始化值;(如int count = 5;); - 作用域:变量的有效范围,分为局部变量(方法/代码块内,需手动初始化)和成员变量(类内方法外,有默认值)。
2.2.2 常量
值不可修改的量,用final修饰:
- 定义格式:
final 数据类型 常量名 = 值;(常量名建议全大写,多个单词用下划线分隔); - 例:
final double PI = 3.1415926;、final int MAX_SIZE = 100;。
2.3 运算符
Java运算符按功能分为以下几类,优先级:算术运算符 > 关系运算符 > 逻辑运算符 > 赋值运算符(可加()改变优先级)。
| 类别 | 运算符 | 示例 | 说明 |
|---|---|---|---|
| 算术运算符 | +、-、*、/、%(取余)、++(自增)、–(自减) | 5%2=1;a++(后增) | 整数除法需注意:5/2=2(而非2.5) |
| 关系运算符 | >、<、>=、<=、==(等于)、!=(不等于) | 3>5→false;a==b | 结果为boolean类型 |
| 逻辑运算符 | &&(短路与)、||(短路或)、!(非) | (a>0)&&(b<0) | 短路特性:&&前假则不执行后,||前真则不执行后 |
| 赋值运算符 | =、+=、-=、*=、/=、%= | a+=3 → a = a+3 | 简化代码,自动处理类型转换 |
| 三元运算符 | 条件表达式 ? 表达式1 : 表达式2 | max = (a>b) ? a : b | 条件为真则取表达式1,否则取表达式2 |
2.4 流程控制
2.4.1 分支结构
switch-case:适用于“多值匹配”,支持byte、short、int、char、String(Java 7+)、枚举类型:
switch(变量){case 值1:// 变量 == 值1时执行break;// 跳出switch,不写则穿透到下一个casecase 值2:// 变量 == 值2时执行break;default:// 所有case不匹配时执行}if-else:
if(条件1){// 条件1为true时执行}elseif(条件2){// 条件1假、条件2真时执行}else{// 所有条件都假时执行}2.4.2 循环结构
do-while循环:先执行一次循环体,再判断条件(至少执行一次):
int i =0;do{System.out.println(i); i++;}while(i <10);while循环:适用于未知循环次数,先判断条件再执行:
int i =0;while(i <10){System.out.println(i); i++;// 避免死循环,必须更新变量}for循环:适用于已知循环次数的场景:
// 格式:初始化变量; 循环条件; 变量更新for(int i =0; i <10; i++){System.out.println(i);// 输出0~9}增强for循环(foreach):遍历数组或集合,无需索引:
int[] arr ={1,2,3};for(int num : arr){System.out.println(num);// 输出1、2、3}2.4.3 跳转语句
break:跳出当前循环或switch;continue:跳过当前循环的剩余代码,直接进入下一次循环;return:结束当前方法,返回指定值(若方法有返回值)。
2.5 数组
数组是相同数据类型元素的有序集合,长度固定,存储在堆内存中。
2.5.1 数组定义与初始化
静态初始化(直接指定元素,长度由元素个数决定):
int[] arr2 =newint[]{1,2,3,4,5};int[] arr3 ={1,2,3,4,5};// 简化写法动态初始化(先指定长度,再赋值):
int[] arr1 =newint[5];// 长度为5,默认值0 arr1[0]=1;// 给第一个元素赋值2.5.2 数组操作
- 获取长度:
arr.length(注意:数组长度不可变,length是属性而非方法); - 访问元素:
arr[index](index从0开始,若超出范围会抛出ArrayIndexOutOfBoundsException); - 遍历数组:用for循环或增强for循环(见2.4.2);
数组工具类:java.util.Arrays,提供排序(sort())、查找(binarySearch())、复制(copyOf())等方法:
importjava.util.Arrays;int[] arr ={3,1,2};Arrays.sort(arr);// 排序后:[1,2,3]System.out.println(Arrays.binarySearch(arr,2));// 查找2的索引:1三、面向对象进阶
3.1 类与对象
3.1.1 类的定义
类是“对象的模板”,包含成员变量(属性)和成员方法(行为):
// 定义Person类publicclassPerson{// 成员变量(属性)privateString name;// 私有,需通过getter/setter访问privateint age;// 构造方法(无参):用于创建对象,若不定义则默认生成publicPerson(){}// 构造方法(有参):用于创建对象时直接赋值publicPerson(String name,int age){this.name = name;// this代表当前对象,区分成员变量和局部变量this.age = age;}// 成员方法(行为)publicvoidsayHello(){System.out.println("Hello, I'm "+ name +", "+ age +" years old.");}// getter/setter方法(访问私有成员变量)publicStringgetName(){return name;}publicvoidsetName(String name){this.name = name;}publicintgetAge(){return age;}publicvoidsetAge(int age){// 可添加逻辑校验if(age >0&& age <150){this.age = age;}else{System.out.println("年龄不合法");}}}3.1.2 对象的创建与使用
通过new关键字调用构造方法创建对象:
// 1. 调用无参构造器创建对象,再通过setter赋值Person p1 =newPerson(); p1.setName("Alice"); p1.setAge(25); p1.sayHello();// 输出:Hello, I'm Alice, 25 years old.// 2. 调用有参构造器创建对象(直接赋值)Person p2 =newPerson("Bob",30);System.out.println(p2.getName());// 输出:Bob3.2 继承与重写
3.2.1 继承的实现
用extends关键字实现继承,子类可访问父类的public、protected成员(private成员不可直接访问):
// 定义父类AnimalpublicclassAnimal{protectedString name;// 受保护的成员,子类可访问publicAnimal(String name){this.name = name;}publicvoideat(){System.out.println(name +" is eating.");}}// 定义子类Dog,继承AnimalpublicclassDogextendsAnimal{// 子类构造器必须先调用父类构造器(用super())publicDog(String name){super(name);// 调用父类有参构造器,必须放在第一行}// 方法重写:子类重写父类的eat()方法@Override// 注解:检查重写语法是否正确(可选但推荐)publicvoideat(){System.out.println(name +" is eating bones.");// 子类特有实现}// 子类特有方法publicvoidbark(){System.out.println(name +" is barking: Wang!");}}3.2.2 方法重写规则
- 方法名、参数列表(个数、类型、顺序)必须与父类完全一致;
- 返回值类型:子类返回值 ≤ 父类返回值(若父类返回
Animal,子类可返回Dog); - 访问权限:子类权限 ≥ 父类权限(若父类是
protected,子类可是public,不可是private); - 父类
final方法不可被重写。
3.3 抽象类与接口
3.3.1 抽象类(abstract class)
包含抽象方法(无实现体的方法)的类,用abstract修饰,不能直接实例化,需子类继承并实现抽象方法:
// 抽象类publicabstractclassShape{// 抽象方法(无方法体,需子类实现)publicabstractdoublegetArea();// 普通方法(有实现体)publicvoidprintInfo(){System.out.println("这是一个图形");}}// 子类Circle继承抽象类,必须实现抽象方法publicclassCircleextendsShape{privatedouble radius;publicCircle(double radius){this.radius = radius;}// 实现抽象方法getArea()@OverridepublicdoublegetArea(){returnMath.PI * radius * radius;}}// 使用:父类引用指向子类对象(多态)Shape circle =newCircle(2.0);System.out.println(circle.getArea());// 输出:12.566...3.3.2 接口(interface)
完全抽象的“契约”,只定义方法签名(无实现)和常量,用interface修饰,类通过implements实现接口:
// 定义接口publicinterfaceFlyable{// 接口中常量默认是public static final(可省略)int MAX_HEIGHT =10000;// 接口中方法默认是public abstract(可省略,Java 8前)voidfly();// Java 8+:默认方法(有实现体,子类可重写)defaultvoidland(){System.out.println("降落中...");}// Java 8+:静态方法(有实现体,通过接口名调用)staticvoidshowMaxHeight(){System.out.println("最大飞行高度:"+ MAX_HEIGHT);}}// 类实现接口,必须实现抽象方法publicclassBirdimplementsFlyable{@Overridepublicvoidfly(){System.out.println("鸟在天上飞");}}// 使用Flyable bird =newBird(); bird.fly();// 输出:鸟在天上飞 bird.land();// 输出:降落中...Flyable.showMaxHeight();// 输出:最大飞行高度:100003.3.3 抽象类 vs 接口
| 维度 | 抽象类(abstract class) | 接口(interface) |
|---|---|---|
| 继承/实现 | 子类用extends单继承 | 类用implements多实现(可实现多个接口) |
| 方法 | 可包含抽象方法、普通方法、静态方法 | Java 8前仅抽象方法;8+可包含默认方法、静态方法 |
| 成员变量 | 可包含任意修饰符的变量(private、public等) | 仅public static final常量(默认) |
| 实例化 | 不能直接实例化,需子类实例化 | 不能实例化,需实现类实例化 |
| 设计意图 | 体现“is-a”关系(如Dog is a Animal),用于代码复用 | 体现“has-a”能力(如Bird has a Flyable能力),用于解耦 |
3.4 关键字详解
3.4.1 final
- 修饰类:类不可被继承(如
java.lang.String是final类); - 修饰方法:方法不可被重写;
- 修饰变量:变量值不可修改(基本类型值不变,引用类型地址不变)。
3.4.2 static
- 修饰成员变量:静态变量,属于“类”而非对象,所有对象共享,通过
类名.变量名访问(如Math.PI); - 修饰成员方法:静态方法,属于类,可直接通过
类名.方法名调用(如Arrays.sort()),不能访问非静态成员(非静态成员属于对象,静态方法调用时可能无对象); - 修饰代码块:静态代码块,类加载时执行一次,用于初始化静态变量(优先于构造方法执行)。
3.4.3 this vs super
| 关键字 | 作用 | 访问成员变量 | 调用构造方法 |
|---|---|---|---|
| this | 代表当前对象 | this.变量名(区分成员与局部变量) | this()(调用当前类其他构造器,需在第一行) |
| super | 代表父类对象 | super.变量名(访问父类成员) | super()(调用父类构造器,需在第一行) |
四、异常处理
4.1 异常体系
Java异常继承自Throwable,分为两大类:
- Error(错误):JVM级别的严重错误,无法通过代码处理(如
OutOfMemoryError、StackOverflowError); - Exception(异常):程序运行中的异常,可通过代码处理,分为:
- 编译时异常(checked exception):编译时必须处理(捕获或抛出),如
IOException、SQLException; - 运行时异常(unchecked exception):编译时无需处理,运行时才可能抛出,如
NullPointerException(空指针)、ArrayIndexOutOfBoundsException(数组越界)。
- 编译时异常(checked exception):编译时必须处理(捕获或抛出),如
4.2 异常处理机制
通过try-catch-finally-throw-throws处理异常:
importjava.io.File;importjava.io.FileNotFoundException;publicclassExceptionDemo{// throws:声明方法可能抛出的异常,由调用者处理publicstaticvoidreadFile(String path)throwsFileNotFoundException{File file =newFile(path);if(!file.exists()){// throw:手动抛出异常(创建异常对象并抛出)thrownewFileNotFoundException("文件不存在:"+ path);}System.out.println("文件存在,开始读取...");}publicstaticvoidmain(String[] args){try{// try:包裹可能抛出异常的代码readFile("D:/test.txt");}catch(FileNotFoundException e){// catch:捕获并处理异常(e为异常对象) e.printStackTrace();// 打印异常栈信息(定位错误)System.out.println("处理异常:"+ e.getMessage());}finally{// finally:无论是否发生异常,都会执行(用于释放资源,如关闭流、连接)System.out.println("无论如何都会执行的代码");}}}4.3 自定义异常
当Java内置异常无法满足需求时,可自定义异常(继承Exception或RuntimeException):
// 自定义编译时异常(继承Exception)publicclassAgeIllegalExceptionextendsException{// 构造方法(调用父类构造器)publicAgeIllegalException(){super();}publicAgeIllegalException(String message){super(message);// 异常信息}}// 使用自定义异常publicclassPersonService{publicvoidsetAge(int age)throwsAgeIllegalException{if(age <0|| age >150){thrownewAgeIllegalException("年龄不合法:"+ age);}}}五、常用类
5.1 String类
java.lang.String是不可变字符串(底层是final char[]),常用方法:
| 方法名 | 作用 | 示例 |
|---|---|---|
length() | 获取字符串长度 | "abc".length() → 3 |
charAt(int index) | 获取指定索引的字符 | "abc".charAt(1) → 'b' |
equals(Object obj) | 比较字符串内容(区分大小写) | "abc".equals("ABC") → false |
equalsIgnoreCase() | 比较字符串内容(不区分大小写) | "abc".equalsIgnoreCase("ABC") → true |
contains(CharSequence s) | 判断是否包含子串 | "hello".contains("ell") → true |
substring(int beginIndex) | 从beginIndex截取子串 | "hello".substring(2) → "llo" |
replace(CharSequence old, CharSequence new) | 替换字符/子串 | "hello".replace('l','x') → "hexxo" |
split(String regex) | 按正则分割字符串,返回数组 | "a,b,c".split(",") → ["a","b","c"] |
trim() | 去除首尾空格 | " hello ".trim() → "hello" |
5.1.1 String、StringBuilder、StringBuffer
- String:不可变,每次修改都会创建新对象(效率低,适合少量修改);
- StringBuilder:可变,线程不安全(效率高,适合单线程);
StringBuffer:可变,线程安全(效率低,适合多线程)。
例(字符串拼接推荐用StringBuilder):
StringBuilder sb =newStringBuilder(); sb.append("Hello"); sb.append(" "); sb.append("World");System.out.println(sb.toString());// 输出:Hello World5.2 包装类
为基本数据类型提供“对象化”支持(如泛型只支持引用类型,需用包装类),8种基本类型对应8种包装类:
| 基本类型 | 包装类 | 基本类型 | 包装类 |
|---|---|---|---|
| byte | Byte | float | Float |
| short | Short | double | Double |
| int | Integer | char | Character |
| long | Long | boolean | Boolean |
5.2.1 自动装箱与拆箱(Java 5+)
- 自动装箱:基本类型 → 包装类(如
int → Integer);
自动拆箱:包装类 → 基本类型(如Integer → int)。
例:
Integer i =10;// 自动装箱(等价于Integer i = Integer.valueOf(10);)int j = i;// 自动拆箱(等价于int j = i.intValue();)注意:Integer缓存-128~127的对象,若值在范围内,==比较为true;超出范围则==比较地址(为false),推荐用equals()比较值。
5.3 日期时间类
Java 8前用java.util.Date、SimpleDateFormat,但线程不安全;Java 8+推荐用java.time包下的线程安全类(如LocalDate、LocalTime、LocalDateTime)。
5.3.1 Java 8+ 日期时间类
importjava.time.LocalDateTime;importjava.time.format.DateTimeFormatter;publicclassDateTimeDemo{publicstaticvoidmain(String[] args){// 1. 获取当前日期时间LocalDateTime now =LocalDateTime.now();System.out.println("当前时间:"+ now);// 输出:2024-05-20T15:30:45.123// 2. 格式化日期时间(DateTimeFormatter:线程安全)DateTimeFormatter formatter =DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");String formattedNow = now.format(formatter);System.out.println("格式化后:"+ formattedNow);// 输出:2024-05-20 15:30:45// 3. 解析字符串为日期时间String dateStr ="2024-01-01 10:00:00";LocalDateTime parsedTime =LocalDateTime.parse(dateStr, formatter);System.out.println("解析后:"+ parsedTime);// 输出:2024-01-01T10:00// 4. 日期时间计算(如加1天、减2小时)LocalDateTime nextDay = now.plusDays(1);LocalDateTime twoHoursAgo = now.minusHours(2);System.out.println("明天此时:"+ nextDay.format(formatter));}}六、集合框架
Java集合框架(java.util.Collection)用于存储多个对象,分为单列集合(Collection)和双列集合(Map),核心接口及实现类如下:
6.1 单列集合(Collection)
存储单个元素,主要有List、Set、Queue三个子接口:
6.1.1 List(有序、可重复)
- ArrayList:底层是动态数组,查询快(随机访问)、增删慢(需移动元素),线程不安全;
- LinkedList:底层是双向链表,查询慢、增删快(只需修改指针),线程不安全;
- Vector:底层是动态数组,线程安全(效率低,已被ArrayList替代)。
常用方法(以ArrayList为例):
importjava.util.ArrayList;importjava.util.List;publicclassListDemo{publicstaticvoidmain(String[] args){List<String> list =newArrayList<>();// 添加元素 list.add("Apple"); list.add("Banana"); list.add(1,"Orange");// 在索引1处插入// 获取元素System.out.println(list.get(0));// 输出:Apple// 修改元素 list.set(2,"Grape");// 将索引2的元素改为Grape// 删除元素 list.remove(1);// 删除索引1的元素 list.remove("Grape");// 删除指定元素// 遍历(三种方式)// 1. for循环for(int i =0; i < list.size(); i++){System.out.println(list.get(i));}// 2. 增强for循环for(String fruit : list){System.out.println(fruit);}// 3. 迭代器(Iterator)java.util.Iterator<String> it = list.iterator();while(it.hasNext()){String fruit = it.next();if(fruit.equals("Apple")){ it.remove();// 迭代器遍历中删除元素(避免ConcurrentModificationException)}}}}6.1.2 Set(无序、不可重复)
- HashSet:底层是哈希表(数组+链表/红黑树),无序、去重,查询/增删快,线程不安全;去重原理:先比较
hashCode(),再比较equals()(需重写这两个方法); - LinkedHashSet:底层是哈希表+链表,有序(按插入顺序)、去重,效率略低于HashSet;
- TreeSet:底层是红黑树,有序(按自然排序或自定义排序)、去重,适合排序场景。
例(HashSet去重):
importjava.util.HashSet;importjava.util.Set;classStudent{privateString id;privateString name;// 构造器、getter/setter省略// 重写hashCode()和equals(),确保id相同则视为同一对象@OverridepublicinthashCode(){return id.hashCode();// 哈希值由id决定}@Overridepublicbooleanequals(Object obj){if(this== obj)returntrue;if(obj ==null||getClass()!= obj.getClass())returnfalse;Student student =(Student) obj;return id.equals(student.id);}}publicclassSetDemo{publicstaticvoidmain(String[] args){Set<Student> set =newHashSet<>(); set.add(newStudent("001","Alice")); set.add(newStudent("001","Alice"));// 重复,不会添加 set.add(newStudent("002","Bob"));System.out.println(set.size());// 输出:2(去重成功)}}6.2 双列集合(Map)
存储“键值对(Key-Value)”,Key不可重复,Value可重复,主要实现类:
- HashMap:底层是哈希表,无序、Key唯一,查询/增删快,线程不安全(Java 8前:数组+链表;Java 8后:数组+链表/红黑树);
- LinkedHashMap:底层是哈希表+链表,有序(按插入顺序),效率略低于HashMap;
- TreeMap:底层是红黑树,Key有序(自然排序或自定义排序),适合按Key排序场景;
- Hashtable:底层是哈希表,线程安全(效率低,已被HashMap替代)。
常用方法(以HashMap为例):
importjava.util.HashMap;importjava.util.Map;importjava.util.Set;publicclassMapDemo{publicstaticvoidmain(String[] args){Map<String,Integer> map =newHashMap<>();// 添加键值对 map.put("Alice",25); map.put("Bob",30); map.put("Charlie",28);// 获取值System.out.println(map.get("Bob"));// 输出:30// 修改值 map.put("Bob",31);// Key存在则覆盖Value// 删除键值对 map.remove("Charlie");// 判断Key是否存在System.out.println(map.containsKey("Alice"));// 输出:true// 遍历Map(两种方式)// 1. 遍历Key集合,再获取ValueSet<String> keySet = map.keySet();for(String name : keySet){System.out.println(name +": "+ map.get(name));}// 2. 遍历Entry集合(Key-Value对)Set<Map.Entry<String,Integer>> entrySet = map.entrySet();for(Map.Entry<String,Integer> entry : entrySet){System.out.println(entry.getKey()+": "+ entry.getValue());}}}七、总结
Java基础知识围绕“面向对象”核心,从语法(数据类型、流程控制、数组)到进阶(类与对象、继承、多态、异常),再到常用工具(集合、日期类、String),构成了Java开发的基础体系。掌握这些知识后,可进一步学习Java高级特性(如多线程、IO流、反射、注解)、框架(Spring、MyBatis)及实战开发(后端接口、Android应用)。
学习建议:理论结合实践,通过编写小案例(如学生管理系统、图书管理系统)巩固知识点,同时关注Java版本更新(如Java 8的Lambda、Stream API,Java 11的新特性),提升开发效率。