Java 是一门强类型、面向对象、跨平台、静态编译型编程语言,其基础语法是构建程序逻辑、数据存储、流程调度、代码规范的核心基石。数据类型决定内存结构,运算符实现数据运算,流程控制控制执行逻辑,数组实现批量存储,枚举限定固定取值,注解提供元数据标记。六者构成 Java 最底层、最基础、最不可缺失的语法体系,是后端开发、校招笔试、面试基础问答的必考核心。
本文以学术严谨性、工程实用性为标准,系统性拆解 Java 基础语法六大模块,逐层剖析底层原理、语法规则、易错陷阱,并配套嵌入式高频面试真题,实现理论学习与面试刷题一体化掌握。
一、Java 数据类型(强类型核心)
Java 是强类型语言,所有变量必须先声明类型、再使用,类型不可随意变更。数据类型分为基本数据类型与引用数据类型两大类,二者在内存存储、赋值机制、默认值上存在本质区别。
1.1 基本数据类型(8 大内置类型)
基本类型直接将值存储在栈内存,无属性与方法,共分为4大类8种:
- 整型:
byte(1字节)、short(2字节)、int(4字节)、long(8字节) - 浮点型:
float(4字节)、double(8字节) - 字符型:
char(2字节) - 布尔型:
boolean(1字节)
// 基本类型声明
int age = 20;
double score = 99.5;
boolean flag = true;
char ch = 'A';
1.2 引用数据类型
除8大基本类型外,其余均为引用类型,包含:类、接口、数组、枚举、注解等。
引用类型变量在栈内存中存储堆内存对象的地址,实际数据存于堆内存,默认值为 null。
String str = "hello";
int[] arr = {1,2,3};
1.3 自动装箱与拆箱
装箱与拆箱是基本类型和对应包装类之间的自动转换机制,由编译器自动完成:
- 装箱:基本类型 → 包装类
- 拆箱:包装类 → 基本类型
Integer a = 10; // 自动装箱
int b = a; // 自动拆箱
本节配套面试真题:Integer 缓存机制
题目:判断代码运行结果
Integer a = 100;
Integer b = 100;
Integer c = 200;
Integer d = 200;
System.out.println(a == b);
System.out.println(c == d);
答案:true、false
解析:Integer 存在常量池缓存,默认缓存范围 -128 ~ 127。该区间内的数值会复用缓存对象,== 比较地址结果为true;超出范围会新建对象,地址不同结果为false。
二、Java 运算符
运算符用于完成数据运算、赋值、比较、逻辑判断等操作,Java 运算符拥有明确的优先级与结合性,按功能可分为多类。
2.1 算术运算符
包含:+、-、*、/、%、++、--
- 整数相除结果仍为整数,小数部分直接舍弃;
- 自增/自减:
++在前,先自增再运算;++在后,先运算再自增。
2.2 赋值运算符
包含:=、+=、-=、*=、/=、%=
复合赋值运算符底层隐含强制类型转换,可简化代码书写。
2.3 比较运算符
包含:==、!=、>、<、>=、<=
- 基本类型:
==比较数值本身; - 引用类型:
==比较内存地址,如需比较内容需重写equals()方法。
2.4 逻辑运算符
包含:&、|、^、!、&&、||
核心特性:短路逻辑。&&(短路与)、||(短路或)若左侧表达式可确定最终结果,右侧表达式不会执行;&、| 无短路特性,两侧都会执行。
2.5 三元运算符
语法:条件表达式 ? 表达式1 : 表达式2
条件为true执行表达式1,为false执行表达式2,属于简写的分支判断。
int a = 10, b = 20;
int max = a > b ? a : b;
本节配套面试真题:短路逻辑陷阱
题目:写出代码输出结果
int num = 10;
boolean res = (num > 20) && (++num > 15);
System.out.println(num);
答案:10
解析:num > 20 结果为false,&& 触发短路,右侧++num不会执行,变量值保持不变。
三、流程控制
流程控制用于改变代码默认的顺序执行逻辑,分为分支结构、循环结构、跳转语句三大类,是实现业务逻辑的基础。
3.1 分支结构
3.1.1 if / else if / else
适用于区间判断、多条件组合判断,支持嵌套使用。
int score = 85;
if (score >= 90) {
System.out.println("优秀");
} else if (score >= 80) {
System.out.println("良好");
} else {
System.out.println("及格");
}
3.1.2 switch 分支
适用于固定等值判断,支持 byte、short、int、char、枚举、String(JDK7+)。
- 必须搭配
break防止穿透现象; default为默认分支,可选配置。
int week = 3;
switch (week) {
case 1:
System.out.println("周一");
break;
case 3:
System.out.println("周三");
break;
default:
System.out.println("未知");
}
3.2 循环结构
3.2.1 for 循环
适合已知循环次数的场景,结构紧凑,使用频率最高。
// 打印 1~5
for (int i = 1; i <= 5; i++) {
System.out.println(i);
}
3.2.2 while 循环
先判断条件,再执行循环体,适合未知循环次数场景。
int i = 1;
while (i <= 5) {
System.out.println(i);
i++;
}
3.2.3 do-while 循环
先执行一次循环体,再判断条件,循环体至少执行一次。
int i = 1;
do {
System.out.println(i);
i++;
} while (i <= 5);
3.3 跳转语句
break:终止当前循环或switch语句;continue:跳过本次循环,直接进入下一次循环;return:结束当前方法。
本节配套面试真题:switch 穿透问题
题目:简述 switch 穿透现象及解决方案
答案:当case分支未写break时,代码会继续执行后续case分支,该现象称为穿透。
解决方案:每个case分支末尾添加break关键字;若业务需要利用穿透特性,可刻意省略。
四、数组
数组是相同数据类型元素的有序集合,属于引用类型,长度固定不可修改,用于批量存储一组数据。
4.1 数组初始化
4.1.1 静态初始化
直接赋值元素,由编译器自动判定数组长度。
// 完整写法
int[] arr1 = new int[]{1,2,3};
// 简化写法
int[] arr2 = {4,5,6};
4.1.2 动态初始化
仅指定数组长度,元素自动赋予对应类型默认值。
// 长度为5,int默认值为0
int[] arr = new int[5];
4.2 数组遍历
4.2.1 普通 for 循环
通过下标遍历,可修改数组元素。
int[] arr = {10,20,30};
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
4.2.2 增强 for 循环(foreach)
简化遍历写法,仅可读取元素,无法修改。
for (int num : arr) {
System.out.println(num);
}
4.3 二维数组
数组中的元素仍是数组,常用于表格、矩阵等场景。
// 动态初始化
int[][] twoArr = new int[2][3];
// 静态初始化
int[][] twoArr2 = {{1,2},{3,4,5}};
4.4 常见问题
- 数组下标从
0开始,最大下标为数组长度-1,访问越界会抛出ArrayIndexOutOfBoundsException; - 数组长度固定,一旦初始化无法扩容。
本节配套面试真题
题目:数组属于基本类型还是引用类型?数组长度能否修改?
答案:数组属于引用类型;Java 数组长度在初始化后固定,无法直接修改,如需扩容只能新建数组并拷贝元素。
五、枚举(Enum)
枚举是 JDK1.5 新增特性,用于定义固定范围的常量集合,可以约束取值范围,替代传统静态常量,类型安全、可读性更强。
5.1 基础语法
使用 enum 关键字定义枚举,枚举项需定义在类首行。
// 定义季节枚举
enum Season {
SPRING, SUMMER, AUTUMN, WINTER
}
5.2 枚举常用方法
values():获取所有枚举项,返回枚举数组;ordinal():获取枚举项的序号(从0开始);name():获取枚举项名称;valueOf():根据名称获取对应枚举项。
Season[] seasons = Season.values();
for (Season s : seasons) {
System.out.println(s.name() + " 序号:" + s.ordinal());
}
5.3 带属性与方法的枚举
枚举本质是特殊的类,可以拥有成员变量、构造方法、普通方法。枚举构造方法默认私有,且只能为 private。
enum Color {
RED("红色", 1),
BLUE("蓝色", 2);
private String name;
private int code;
// 私有构造方法
Color(String name, int code) {
this.name = name;
this.code = code;
}
public String getName() {
return name;
}
}
本节配套面试真题
题目:枚举能否被继承?枚举的构造方法为什么必须是私有的?
答案:1. 枚举默认隐式继承 java.lang.Enum,无法再继承其他类,也不能被普通类继承;2. 枚举是固定常量集合,为防止外部随意创建枚举对象,因此构造方法强制私有。
六、注解(Annotation)
注解是 JDK1.5 新增的元数据标签,用于为代码添加附加信息,不影响程序核心逻辑,可在编译期、运行期被解析使用。广泛用于配置、框架标记、代码校验等场景。
6.1 内置常用注解
Java 原生提供多个核心注解:
@Override:标记方法为重写父类/接口方法,编译器校验语法合法性;@Deprecated:标记方法/类已过时,提示开发者不建议使用;@SuppressWarnings:压制编译器警告;@FunctionalInterface:标记函数式接口(JDK8+)。
6.2 元注解
用于修饰自定义注解的注解,共4个核心元注解:
@Target:指定注解的使用位置(类、方法、变量、参数等);@Retention:指定注解的生命周期(源码期、编译期、运行期);@Documented:注解信息会被提取到 API 文档;@Inherited:子类可继承父类上的该注解。
6.3 自定义注解
结合元注解定义专属注解,配合反射可实现注解解析。
import java.lang.annotation.*;
// 自定义注解
@Target(ElementType.METHOD) // 作用在方法上
@Retention(RetentionPolicy.RUNTIME) // 运行时有效
public @interface MyAnnotation {
// 注解属性
String value() default "";
}
// 使用自定义注解
public class Test {
@MyAnnotation("测试注解")
public void test(){}
}
本节配套面试真题
题目:简述 @Retention 三种生命周期区别
答案:
1. SOURCE:仅存在于源码阶段,编译后丢弃;
2. CLASS:保留到编译后的 class 文件,运行时 JVM 不加载(默认级别);
3. RUNTIME:保留至程序运行阶段,可通过反射获取注解信息,框架中使用最多。
七、全文终极背诵总结
1. 数据类型:分为基本类型(8种,栈存储)和引用类型(堆存储,默认null);包装类存在自动装箱拆箱,Integer 缓存区间 -128~127。
2. 运算符:区分==对基本类型和引用类型的判断逻辑,逻辑运算符注意短路特性,复合赋值运算符隐含强转。
3. 流程控制:if适合区间判断,switch适合等值判断;循环分for/while/do-while,do-while至少执行一次。
4. 数组:引用类型,长度固定不可修改,下标从0开始,越界会抛出异常;支持普通遍历与增强for遍历。
5. 枚举:约束固定常量取值,本质是特殊类,构造方法私有,无法被继承,类型安全性优于静态常量。
6. 注解:代码元数据,内置注解用于基础标记,元注解用于定义注解,运行时注解可配合反射实现业务逻辑。