Java 语法基础
JDK 的组成
- JVM(Java 虚拟机):一种能将编译后的 Java 字节码(.class 文件)加载、验证、解释或即时编译并执行的抽象计算机环境。
- JRE(Java 运行时环境):包含 JVM、核心类库和其他必需组件,用于在本地系统上运行 Java 应用程序的完整环境。
- JDK(Java 开发工具包):在 JRE 基础上额外提供 Java 编译器(javac)、调试器等开发工具,用于编写和调试 Java 程序的套件。
注释类型
单行注释(Single-line Comment)
以//开头,直到行尾都被视为注释。1
2// 这是一个单行注释
int x = 10; // 也可以放在代码行末多行注释(Block Comment)
以/*开始,以*/结束,适合注释多行内容。1
2
3
4
5/*
* 这是一个多行注释
* 可以覆盖多行文字
*/
int y = 20;文档注释(Javadoc Comment)
以/**开始,以*/结束,通常用于生成 API 文档,可放在类、方法、字段等声明之前。1
2
3
4
5
6
7
8
9
10/**
* 计算两个整数的和。
*
* @param a 第一个加数
* @param b 第二个加数
* @return 返回 a 与 b 的和
*/
public int add(int a, int b) {
return a + b;
}
字面量
- 整数字面量(Integer Literals)
- 十进制:
123,0 - 八进制(以
0开头):075(等于十进制 61) - 十六进制(以
0x或0X开头):0xFF,0X1A3 - 二进制(Java 7+,以
0b或0B开头):0b1010,0B1101 - 长整型后缀:在数字后加
L或l,如12345678901L
- 十进制:
- 浮点数字面量(Floating-Point Literals)
- 十进制形式:
3.14,0.001,2. - 科学计数法:
1.23e3(×10³),4.56E-2(×10⁻²) - 单精度后缀:在数字后加
F或f,如3.14F - 双精度默认:如
2.71828(等同于2.71828D)
- 十进制形式:
- 字符字面量(Character Literals)
- 单引号括起的单个字符:
'a','中','$' - 支持转义序列:
\n,'\u4E2D','\''
- 单引号括起的单个字符:
- 字符串字面量(String Literals)
- 双引号括起的字符序列:
"Hello, Java!","换行:\n下一行" - 支持所有字符转义:
\t,\",\\等
- 双引号括起的字符序列:
- 布尔字面量(Boolean Literals)
- 只有两个取值:
true和false
- 只有两个取值:
- 空字面量(Null Literal)
- 用于表示引用类型不指向任何对象:
null
- 用于表示引用类型不指向任何对象:
变量声明
1 | [修饰符列表] 数据类型 变量名 [= 初始值] [, 变量名 [= 初始值] …] ; |
变量修饰符
package-private(默认)
不加任何访问修饰符时,称为包级私有。变量只对同一包内的类可见,包外不可访问。public
公开访问权限,声明为public的变量对所有类可见,无论是否在同一包中。protected
受保护访问权限,声明为protected的变量对同一包内的类及所有子类可见(即使子类在不同包中)。private
私有访问权限,声明为private的变量仅在当前类内部可见,外部类和子类均无法直接访问。static
静态变量属于类本身而非某个实例。所有对象共享同一份static变量,且可以通过ClassName.var直接访问。final
常量修饰符,声明后必须在定义处或构造器中赋值,且赋值一次后不可再修改,常用于定义不可变值。transient
瞬态修饰符,指示该变量在对象序列化(Serializable)时不被持久化写入序列化流。volatile
易变修饰符,保证多个线程访问该变量时的可见性和有序性:对一个线程写入的值,其他线程能立即看到,不会被线程本地缓存长期“隐藏”。
存储区域
- 局部变量 → 线程栈;实例变量 → 堆;静态变量 → 方法区。
基本类型 vs 引用类型
- 基本类型存值;引用类型存地址,实际对象在堆上。
变量访问
- 字节码通过
load/store(局部变量)和get/put(实例/静态变量)在操作数栈与内存区间搬运数据。
并发可见性
- 每线程独立栈;堆与方法区共享;
volatile和synchronized保证跨线程可见性与有序性。
生命周期
- 栈上随方法调用进出;静态随类加载/卸载;堆上随对象引用消失由 GC 回收。
自动类型转换
- 数值类型“向上”转换:编译器自动将容量小的类型提升到容量大的类型,顺序为
byte → short → int → long → float → double,并且在算术运算中,byte/short/char会先提升为int。 char到整数:char可自动转为int及更大类型。- 引用类型“向上”转型:子类对象可赋给父类引用,无需显式转换。
- 限制:只能“扩宽”或“子 → 父”,反之(“窄化”或“父 → 子”)必须显式强制转换。
强制类型转换
基本类型转换
窄化转换(大 → 小):需
(目标类型) 值,可能截断或溢出。1
2int i = (int) 3.9; // i = 3
byte b = (byte) 130; // b = -126拓宽转换(小 → 大):自动完成,无需显式。
引用类型转换
上转型(子 → 父):隐式安全。
1
Animal a = new Dog();
下转型(父 → 子):需
(子类) 父引用,若类型不符抛ClassCastException。1
2
3if (a instanceof Dog) {
Dog d = (Dog) a;
}
常见注意点
- 混合运算:整型运算默升为
int,赋小类型需显式转。 - 精度控制:如
(double) a / b保留小数。 - 泛型前代码:对
Object集合取出时需要转换,推荐使用泛型避免。
- 混合运算:整型运算默升为
要点:大 → 小要显式转换并谨防数据丢失;父 → 子要确认类型再转。
运算符
算术运算符
+、-、*、/、%- 自增/自减:
++a、a++、--a、a--
赋值运算符
- 简单赋值:
= - 复合赋值:
+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=、>>>=
- 简单赋值:
关系(比较)运算符
==、!=>、<、>=、<=
逻辑运算符
- 与:
&&(短路),&(非短路) - 或:
||(短路),|(非短路) - 非:
!
- 与:
位运算符
- 与:
& - 或:
| - 异或:
^ - 取反:
~
- 与:
位移运算符
- 左移:
<< - 右移(带符号):
>> - 右移(无符号):
>>>
- 左移:
三元运算符
condition ? expr1 : expr2
1
int max = (a > b) ? a : b;
其他运算符
- 类型检查:
instanceof - 数组下标:
[] - 方法调用:
() - 成员访问:
.、->(仅用于 JNI) - 强制类型转换:
(Type) value
- 类型检查:
提示:运算符优先级影响表达式计算顺序,可参考官方文档或使用括号
()来明确运算顺序。
程序流程控制
顺序执行
按代码书写顺序从上到下依次执行。分支(选择)
if/if–else/if–else if–else1
2
3if (cond) { … }
else if (cond2) { … }
else { … }switch1
2
3
4
5switch (expr) {
case 常量1: …; break;
case 常量2: …; break;
default: …;
}
循环(迭代)
for循环1
2
3for (初始化; 条件; 更新) {
…
}**增强型
for**(遍历数组/集合)1
2
3for (Type item : collection) {
…
}while循环1
2
3while (条件) {
…
}do–while循环1
2
3do {
…
} while (条件);
跳转控制
break:退出最近的switch或循环continue:跳过本次循环、进入下一次迭代return:结束方法并可返回值
异常处理
捕获/处理:
try–catch–finally1
2
3
4
5
6
7try {
…
} catch (ExceptionType e) {
…
} finally {
…
}抛出异常:
throw new ExceptionType("msg");
要点:
- 用分支 (
if/switch) 做条件判断,- 用各种
for/while循环重复执行,- 配合
break/continue控制循环流程,- 用异常 (
try–catch) 管理错误场景。
数组
1. 数组的定义
一维数组
1
2
3
4
5
6// 声明
int[] arr1;
String arr2[];
// 分配空间并初始化
arr1 = new int[5];
String[] arr3 = new String[] { "A", "B", "C" };多维数组
1
2
3
4
5
6// 二维数组
int[][] matrix = new int[3][4];
// 不规则二维数组
int[][] ragged = new int[3][];
ragged[0] = new int[2];
ragged[1] = new int[5];
2. 数组的遍历
传统
for循环1
2
3for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}增强型
for(foreach)1
2
3for (String s : arr) {
System.out.println(s);
}while/do–while1
2
3
4int i = 0;
while (i < arr.length) {
System.out.println(arr[i++]);
}
3. 存储原理
连续内存
数组在内存中占用一段连续空间,每个元素大小相同(基于元素类型)。索引访问
通过索引直接计算元素地址:1
元素地址 = 数组基地址 + 索引 * 元素字节长度
定长特性
数组长度在创建时确定,无法动态扩容;要变更长度需新建数组并复制元素。多维数组
Java 多维数组本质是“数组的数组”,最外层引用指向若干子数组,它们可分别分配内存(支持不规则矩阵)。
要点:
- 定义:用
new Type[size]创建定长、同类型的存储结构;- 遍历:常用
for/ 增强for;- 存储:连续内存+索引直接定位,访问高效但尺寸固定。
方法
定义
1
2
3
4// 语法:[修饰符] 返回类型 方法名(参数列表) { 方法体 }
public int add(int x, int y) {
return x + y;
}执行原理
- 调用时在栈上为方法创建栈帧(包含局部变量、操作数栈等)。
- 执行方法体指令,使用操作数栈进行计算。
- 遇
return弹出栈帧,将返回值(若有)传给调用者。
参数传递
- 基本类型:按值传递,方法内修改不影响外部变量。
- 引用类型:传递的是引用的副本(引用按值传)。方法内可通过该引用修改对象内容,但无法让引用指向新对象影响外部。
重载(Overload)
- 同一类中多个同名方法,参数列表(类型、个数、顺序)必须不同。
- 编译期根据调用时的静态类型和实际参数匹配最优方法签名。
- 与返回类型、抛出异常无关。