引言
Java 作为一门跨平台、面向对象的高级编程语言,其核心基础语法是所有Java开发的基石。无论是入门新手,还是想要进阶架构师的资深开发者,扎实的语法基础都是规避 bug、提升编码效率、深入理解 JVM 底层原理的前提。本文将系统梳理 Java 核心基础语法,结合原理讲解、可运行的实战代码示例与行业通用的避坑指南,帮你彻底吃透 Java 基础。
一、Java 程序的基本结构
1.1 第一个可运行的 Java 程序
所有 Java 代码都必须放在类(class)中,我们先从经典的Hello World程序入手,完整代码如下:
java
// 公共类,类名必须与文件名完全一致
public class HelloWorld {
// 程序入口方法,JVM固定识别的执行入口
public static void main(String[] args) {
// 控制台输出语句
System.out.println("Hello Java!");
}
}
运行说明:
- 将文件保存为
HelloWorld.java(公共类名必须与文件名一致,大小写敏感); - 使用
javac HelloWorld.java编译代码,生成HelloWorld.class字节码文件; - 使用
java HelloWorld运行程序,控制台输出Hello Java!。
1.2 程序结构核心详解
| 代码片段 | 作用与原理 |
|---|---|
public class HelloWorld |
定义一个公共类,public表示类可被全局访问,class是定义类的关键字,HelloWorld是类名 |
public static void main(String[] args) |
Java 程序的唯一固定入口 ,JVM 启动时会自动寻找该方法执行:- public:保证 JVM 可以访问到该方法- static:无需实例化类,直接通过类名调用- void:方法无返回值,JVM 不需要接收返回结果- String[] args:接收命令行传入的参数 |
System.out.println() |
Java 标准输出语句,用于向控制台打印内容,println会自动换行,对应的print不会换行 |
二、标识符与关键字
2.1 标识符的定义与规则
标识符是程序员为类、方法、变量、常量等自定义的名称,必须遵守以下硬性规则:
- 只能由字母(A-Z/a-z)、数字(0-9)、下划线(
_)、美元符($)组成; - 不能以数字开头;
- 不能使用 Java 的关键字、保留字;
- 大小写敏感,
Hello和hello是两个不同的标识符。
2.2 关键字与保留字
- 关键字 :Java 语言赋予了特殊含义的单词,全部小写,共有 50 个,例如
public、class、static、int、if、for等; - 保留字 :Java 预留的、暂无特殊含义但未来可能作为关键字的单词,包括
goto、const,标识符也不能使用这两个单词。
2.3 通用命名规范
| 标识符类型 | 命名规范 | 示例 |
|---|---|---|
| 类名 / 接口名 | 大驼峰命名法,每个单词首字母大写 | UserService、HelloWorld |
| 方法名 / 变量名 | 小驼峰命名法,第一个单词首字母小写,后续单词首字母大写 | getUserName、studentAge |
| 常量名 | 全大写,单词之间用下划线分隔 | MAX_AGE、DEFAULT_TIMEOUT |
| 包名 | 全小写,单词之间用点分隔 | com.example.demo |
三、Java 数据类型体系
Java 是强类型语言,所有变量必须先声明类型、再赋值使用,数据类型分为基本数据类型 和引用数据类型两大类。
3.1 基本数据类型
Java 提供 8 种基本数据类型,分为 4 大类,所有基本类型的取值范围、字节数都是固定的,与平台无关,保证了 Java 的跨平台特性。
| 类型分类 | 类型名 | 占用字节 | 取值范围 | 默认值 | 示例 |
|---|---|---|---|---|---|
| 整数型 | byte |
1 | -128 ~ 127 | 0 | byte age = 18; |
| 整数型 | short |
2 | -32768 ~ 32767 | 0 | short salary = 30000; |
| 整数型 | int |
4 | -2^31 ~ 2^31-1 | 0 | int id = 100001; |
| 整数型 | long |
8 | -2^63 ~ 2^63-1 | 0L | long total = 10000000000L; |
| 浮点型 | float |
4 | 单精度,约 6-7 位有效数字 | 0.0F | float weight = 65.5F; |
| 浮点型 | double |
8 | 双精度,约 15-16 位有效数字 | 0.0D | double height = 175.5; |
| 字符型 | char |
2 | 单个 Unicode 字符,0 ~ 65535 | '\u0000' | char gender = '男'; |
| 布尔型 | boolean |
1bit(JVM 实现) | true/false | false | boolean isAdult = true; |
避坑指南:
long类型的数值必须加后缀L(推荐大写,避免和数字 1 混淆),float类型必须加后缀F,否则会被默认识别为double类型,编译报错;- 浮点型存在精度丢失问题,绝对不能用
==比较两个浮点数 ,商业计算请使用java.math.BigDecimal; char类型使用单引号包裹,只能存放单个字符,和使用双引号的字符串String完全不同。
3.2 引用数据类型
引用数据类型指向堆内存中的对象,包括类、接口、数组、枚举、注解等,String本质是类,属于引用类型。
- 核心区别:基本数据类型的变量直接存储值,存放在栈内存;引用类型的变量存储的是对象的内存地址(引用),对象本身存放在堆内存,引用存放在栈内存。
示例:
java
// 基本类型:直接存储值
int a = 10;
// 引用类型:存储对象的地址
String str = new String("Java");
int[] arr = new int[5];
3.3 类型转换
3.3.1 自动类型转换(隐式转换)
小范围类型可以自动转换为大范围类型,无需手动处理,规则:byte -> short -> int -> long -> float -> double,char可以自动转换为int。示例:
java
int num = 100;
// int自动转换为long
long bigNum = num;
// int自动转换为double
double doubleNum = num;
3.3.2 强制类型转换(显式转换)
大范围类型转换为小范围类型,必须手动强制转换,可能会丢失精度或溢出。语法:(目标类型) 变量/值示例:
java
double pi = 3.1415926;
// 强制转换为int,丢失小数部分,结果为3
int intPi = (int) pi;
byte b = (byte) 130;
// 溢出,结果为-126(超出byte的取值范围,发生循环溢出)
System.out.println(b);
3.4 自动装箱与拆箱
Java 5 及以上版本支持基本类型和对应的包装类之间的自动转换:
- 装箱:基本类型自动转换为包装类(如
int->Integer) - 拆箱:包装类自动转换为基本类型(如
Integer->int)
核心注意点:Integer 缓存池 JVM 会缓存-128 ~ 127范围内的Integer对象,超出范围会新建对象,示例:
java
Integer i1 = 127;
Integer i2 = 127;
// true,使用缓存池中的同一个对象
System.out.println(i1 == i2);
Integer i3 = 128;
Integer i4 = 128;
// false,超出缓存范围,新建了两个不同的对象
System.out.println(i3 == i4);
四、Java 运算符体系
4.1 核心运算符分类与示例
| 运算符类型 | 常用运算符 | 示例 | 说明 | ||
|---|---|---|---|---|---|
| 算术运算符 | +、-、*、/、%、++、-- |
a++、b-- |
%是取余运算;++前置先自增再运算,后置先运算再自增 |
||
| 赋值运算符 | =、+=、-=、*=、/= |
a += 10 等价于 a = a + 10 |
复合赋值运算符会自动强制类型转换 | ||
| 比较运算符 | ==、!=、>、<、>=、<= |
a > 10 |
结果为 boolean 类型的 true/false | ||
| 逻辑运算符 | &&(短路与) |
(短路或)、!`(非) |
a>10 && b<20 |
短路特性:左边表达式能确定结果时,右边不再执行 | |
| 位运算符 | & |
^、<<、>> |
a << 2 等价于 a * 4 |
直接操作二进制位,效率极高 | |
| 三元运算符 | 条件表达式 ? 值1 : 值2 |
a > 18 ? "成年" : "未成年" |
简化的 if-else,根据条件返回对应的值 |
4.2 高频避坑指南
1.短路与非短路的区别:
-
&&:左边为 false 时,右边不执行; -
&:无论左边结果如何,右边一定会执行;示例:javaint a = 10; boolean res1 = (a > 20) && (++a > 10); // 输出10,右边++a没有执行 System.out.println(a); int b = 10; boolean res2 = (b > 20) & (++b > 10); // 输出11,右边++b执行了 System.out.println(b);
2.==与equals()的核心区别:
-
==:比较基本类型时比较值,比较引用类型时比较对象的内存地址; -
equals():本质是类重写后的方法,String等类重写后用于比较对象的内容,未重写的类默认和==一致。示例:javaString s1 = new String("Java"); String s2 = new String("Java"); // false,两个不同的对象,地址不同 System.out.println(s1 == s2); // true,字符串内容相同 System.out.println(s1.equals(s2));五、流程控制语句
5.1 分支结构
5.1.1 if-else 分支
适用于区间判断,语法:
javaint score = 85; if (score >= 90) { System.out.println("优秀"); } else if (score >= 60) { System.out.println("及格"); } else { System.out.println("不及格"); }5.1.2 switch 分支
适用于固定值的匹配,Java 7 支持
String类型,Java 14 + 支持 switch 表达式(简化写法,无需 break)。 -
传统写法(注意 case 穿透):
java
int day = 2;
switch (day) {
case 1:
System.out.println("周一");
break; // 必须加break,否则会发生case穿透
case 2:
System.out.println("周二");
break;
case 3:
System.out.println("周三");
break;
default:
System.out.println("无效日期");
}
- Java 14+ 新写法(switch 表达式,直接返回值):
java
int day = 3;
String dayType = switch (day) {
case 1,2,3,4,5 -> "工作日";
case 6,7 -> "周末";
default -> throw new IllegalArgumentException("无效日期:" + day);
};
// 输出:工作日
System.out.println(dayType);
5.2 循环结构
用于重复执行某段代码,包括for、while、do-while三种。
5.2.1 for 循环
适用于循环次数已知的场景,语法:
java
// 计算1-100的和
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
// 输出5050
System.out.println(sum);
5.2.2 while 循环
适用于循环次数未知的场景,先判断条件,再执行循环体:
java
int i = 1;
int sum = 0;
while (i <= 100) {
sum += i;
i++;
}
5.2.3 do-while 循环
先执行循环体,再判断条件,循环体至少执行一次:
java
int i = 1;
int sum = 0;
do {
sum += i;
i++;
} while (i <= 100);
循环优化技巧:避免在循环终止条件中重复调用方法,例如:
java
// 不推荐:每次循环都会调用list.size()方法
for (int i = 0; i < list.size(); i++) {}
// 推荐:提前获取长度,只调用一次方法
int size = list.size();
for (int i = 0; i < size; i++) {}
5.3 跳转语句
break:终止当前循环或 switch 语句;continue:跳过本次循环,执行下一次循环;return:终止方法执行,返回结果。
六、数组
数组是相同类型数据的有序集合,长度一旦初始化就不可改变,属于引用类型。
6.1 一维数组的定义与初始化
java
// 方式1:静态初始化,指定元素,长度自动确定
int[] arr1 = {1,2,3,4,5};
// 方式2:动态初始化,指定长度,元素为默认值
int[] arr2 = new int[5];
arr2[0] = 1;
arr2[1] = 2;
6.2 数组的遍历
java
int[] arr = {1,2,3,4,5};
// 方式1:普通for循环
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
// 方式2:增强for循环(foreach),无法获取索引
for (int num : arr) {
System.out.println(num);
}
6.3 Arrays 工具类
java.util.Arrays是 Java 提供的数组工具类,封装了常用的数组操作:
java
import java.util.Arrays;
public class ArrayDemo {
public static void main(String[] args) {
int[] arr = {3,1,5,2,4};
// 排序:升序排序
Arrays.sort(arr);
System.out.println(Arrays.toString(arr)); // 输出[1,2,3,4,5]
// 查找:二分查找,必须先排序
int index = Arrays.binarySearch(arr, 3);
System.out.println(index); // 输出2
// 填充:将数组所有元素填充为指定值
Arrays.fill(arr, 0);
System.out.println(Arrays.toString(arr)); // 输出[0,0,0,0,0]
}
}
6.4 常见异常避坑
ArrayIndexOutOfBoundsException:数组下标越界,下标超出[0--数组长度-1]的范围;NullPointerException:空指针异常,数组引用为 null 时操作数组。
七、方法(函数)
方法是封装了特定功能的代码块,实现代码复用,Java 中的方法必须定义在类中。
7.1 方法的定义与格式
java
修饰符 返回值类型 方法名(参数类型 参数名1, 参数类型 参数名2) {
// 方法体
return 返回值;
}
示例:定义一个加法方法
java
public class MethodDemo {
// 定义加法方法
public static int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
// 调用方法
int res = add(10, 20);
System.out.println(res); // 输出30
}
}
7.2 方法的重载(Overload)
方法重载是指 ** 同一个类中,方法名相同,参数列表不同(个数、类型、顺序不同)** 的多个方法,与返回值、修饰符无关,是 Java 多态的一种体现。示例:
java
public class OverloadDemo {
// 两个int相加
public int add(int a, int b) {
return a + b;
}
// 三个int相加,参数个数不同
public int add(int a, int b, int c) {
return a + b + c;
}
// 两个double相加,参数类型不同
public double add(double a, double b) {
return a + b;
}
}
7.3 Java 的参数传递机制:只有值传递
Java 中只有值传递,没有引用传递,核心规则:
- 基本类型参数:传递的是值的副本,方法内修改副本不会影响原变量;
- 引用类型参数:传递的是引用地址的副本,副本和原引用指向同一个堆对象,通过副本修改对象的属性会影响原对象,但修改副本的指向不会影响原引用。
示例 1:基本类型参数传递
java
public class ValuePassDemo {
public static void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
public static void main(String[] args) {
int x = 10;
int y = 20;
swap(x, y);
// 输出x=10, y=20,原变量没有交换
System.out.println("x=" + x + ", y=" + y);
}
}
示例 2:引用类型参数传递
java
class User {
String name;
public User(String name) {
this.name = name;
}
}
public class ReferencePassDemo {
public static void changeName(User user) {
// 修改对象的属性,原对象会被改变
user.name = "李四";
}
public static void main(String[] args) {
User u = new User("张三");
changeName(u);
// 输出李四
System.out.println(u.name);
}
}
总结与进阶方向
本文覆盖了 Java 核心基础语法的全部核心内容,这些语法是 Java 开发的基石,后续的面向对象编程、集合框架、IO 流、多线程、JVM 底层原理、Spring 等框架的学习,都建立在扎实的基础语法之上。