学习 Java,首先要掌握的就是变量、数据类型、运算符和类型转换。这些内容看起来比较基础,但后面学习流程控制、数组、方法以及面向对象时都会频繁用到。
本文通过代码示例,对这几个知识点进行系统整理。
一、变量
1. 什么是变量
程序在运行过程中,经常需要临时保存一些数据,例如姓名、年龄、商品价格和考试成绩。
变量就是用来保存这些数据的。
Java 中声明变量的基本格式如下:
数据类型 变量名 = 初始值;
例如:
int age = 18;
double price = 29.9;
String name = "张三";
其中:
int、double和String是数据类型age、price和name是变量名18、29.9和"张三"是变量的值
变量也可以先声明,再赋值:
int score;
score = 95;
System.out.println(score);
需要注意,局部变量在使用之前必须完成赋值。
下面的代码会编译失败:
int score;
System.out.println(score);
因为此时 score 还没有确定的值。

2. 修改变量的值
变量中的数据可以发生变化:
int age = 18;
age = 20;
System.out.println(age);
运行结果:
20
第二次赋值会覆盖变量原来的值。
不过,变量的数据类型一旦确定,通常就不能保存其他类型的数据:
int age = 18;
// age = "二十";
// 编译错误,int 类型不能保存字符串
3. 变量的命名规则
Java 中的变量名需要遵守以下规则:
- 可以由字母、数字、下划线和美元符号组成。
- 不能以数字开头。
- 不能使用 Java 关键字。
- 变量名区分大小写。
- 变量名中不能包含空格。
- 建议做到见名知意。
正确示例:
int age;
int studentCount;
double productPrice;
String userName;
错误示例:
// int 2age;
// 不能以数字开头
// int class;
// class 是 Java 关键字
// int user-name;
// 不能包含减号
Java 中的变量名通常使用小驼峰命名法。
小驼峰命名法的特点是:
- 第一个单词的首字母小写
- 后续单词的首字母大写
例如:
String studentName;
int maxScore;
double orderAmount;
4. 变量的作用域
变量只能在它所在的大括号范围内使用,这个范围称为变量的作用域。
public class VariableDemo {
public static void main(String[] args) {
int age = 18;
if (age >= 18) {
String message = "已经成年";
System.out.println(message);
}
// System.out.println(message);
// 编译错误,message 只能在 if 的大括号中使用
}
}
在这个例子中,message 声明在 if 的大括号中,所以离开这个范围之后就不能继续使用。
5. 常量
如果一个变量初始化后不允许再次修改,可以使用 final 关键字。
final double PI = 3.1415926;
final int MAX_COUNT = 100;
被 final 修饰的变量只能赋值一次:
final int MAX_COUNT = 100;
// MAX_COUNT = 200;
// 编译错误,不能再次赋值
常量名通常全部使用大写字母,多个单词之间使用下划线连接。
final int MAX_LOGIN_COUNT = 5;
final double DEFAULT_DISCOUNT = 0.9;
二、Java 中的数据类型
Java 是一门强类型语言,每个变量都需要明确自己的数据类型。
Java 中的数据类型主要分为两类:
- 基本数据类型
- 引用数据类型
三、基本数据类型
Java 一共有 8 种基本数据类型。
| 类型 | 占用空间 | 示例 | 主要用途 |
|---|---|---|---|
byte |
1 字节 | byte level = 10; |
保存较小的整数 |
short |
2 字节 | short year = 2026; |
保存短整数 |
int |
4 字节 | int age = 18; |
保存常用整数 |
long |
8 字节 | long number = 100L; |
保存较大的整数 |
float |
4 字节 | float height = 1.75F; |
保存单精度小数 |
double |
8 字节 | double price = 19.99; |
保存双精度小数 |
char |
2 字节 | char grade = 'A'; |
保存单个字符 |
boolean |
与具体实现有关 | boolean result = true; |
保存逻辑值 |
1. 整数类型
Java 中有 4 种整数类型:
byteshortintlong
示例:
byte level = 10;
short year = 2026;
int population = 100000;
long distance = 9999999999L;
日常开发中,整数一般优先使用 int。只有数据可能超出 int 的取值范围时,才考虑使用 long。
整数默认是 int 类型。如果一个整数超过了 int 的取值范围,需要在数字末尾添加 L:
long population = 8_000_000_000L;
推荐使用大写 L,因为小写 l 和数字 1 比较相似,不容易分辨。
数字中间的下划线只用于提高可读性,不会影响数值:
int money = 1_000_000;
System.out.println(money);
运行结果:
1000000
2. 浮点类型
Java 中有两种浮点类型:
floatdouble
示例:
float height = 1.75F;
double price = 199.99;
Java 中的小数字面量默认是 double 类型。
给 float 变量赋值时,需要在数字末尾添加 F:
float score = 95.5F;
下面的写法会编译失败:
// float score = 95.5;
// 95.5 默认是 double 类型
在实际开发中,普通小数一般使用 double。不过,double 也存在精度问题:
double result = 0.1 + 0.2;
System.out.println(result);
运行结果可能是:
0.30000000000000004
因此,在计算商品价格、账户余额等数据时,不建议直接使用 float 或 double,可以使用 BigDecimal。
import java.math.BigDecimal;
public class BigDecimalDemo {
public static void main(String[] args) {
BigDecimal first = new BigDecimal("0.1");
BigDecimal second = new BigDecimal("0.2");
BigDecimal result = first.add(second);
System.out.println(result);
}
}
运行结果:
0.3
创建 BigDecimal 时,建议传入字符串,避免把浮点数本身的误差带进去。传入的是字符串 "0.1",但 BigDecimal 内部会把它解析成高精度十进制数字,不是直接拿字符串做拼接!
3. 字符类型
char 用于保存单个字符,字符需要使用单引号。
char letter = 'A';
char number = '8';
char chinese = '中';
char 只能保存一个字符:
char grade = 'A';
// char name = '张三';
// 编译错误,包含了两个字符
需要区分字符和字符串:
char letter = 'A';
String text = "A";
单引号表示字符,双引号表示字符串。
char 类型本质上保存的是字符对应的编码值,因此它可以参与整数运算:
char letter = 'A';
System.out.println((int) letter);
System.out.println(letter + 1);
运行结果:
65
66
4. 布尔类型
boolean 用来表示逻辑状态,只有两个值:
boolean isLogin = true;
boolean isDeleted = false;
布尔类型经常用于条件判断:
int age = 20;
boolean isAdult = age >= 18;
if (isAdult) {
System.out.println("已经成年");
}
Java 中不能使用 0 或 1 代替布尔值:
// boolean result = 1;
// 编译错误
这也是 Java 和部分编程语言之间的区别。
四、引用数据类型
除了 8 种基本数据类型之外,其他大部分类型都属于引用数据类型,例如:
- 字符串
- 数组
- 类
- 接口
- 枚举
示例:
String name = "张三";
int[] scores = {90, 85, 100};
Object object = new Object();
引用类型可以赋值为 null:
String name = null;
null 表示当前变量没有指向任何对象。
基本数据类型不能直接赋值为 null:
// int age = null;
// 编译错误
五、算术运算符
算术运算符主要用于数学计算。
| 运算符 | 作用 | 示例 |
|---|---|---|
+ |
加法 | a + b |
- |
减法 | a - b |
* |
乘法 | a * b |
/ |
除法 | a / b |
% |
取余 | a % b |
示例:
int a = 10;
int b = 3;
System.out.println(a + b);
System.out.println(a - b);
System.out.println(a * b);
System.out.println(a / b);
System.out.println(a % b);
运行结果:
13
7
30
3
1
1. 整数除法
两个整数相除,得到的结果仍然是整数,小数部分会被直接舍弃。
int result = 10 / 3;
System.out.println(result);
运行结果:
3
如果希望得到小数结果,至少要让其中一个操作数变成浮点数:
double result = 10.0 / 3;
System.out.println(result);
也可以使用类型转换:
int a = 10;
int b = 3;
double result = (double) a / b;
System.out.println(result);
2. 取余运算
% 用于计算两个数相除之后的余数。
int result = 10 % 3;
System.out.println(result);
运行结果:
1
取余运算经常用来判断奇数和偶数:
int number = 10;
if (number % 2 == 0) {
System.out.println("偶数");
} else {
System.out.println("奇数");
}
六、自增和自减运算符
++ 表示变量加 1,-- 表示变量减 1。
int number = 10;
number++;
System.out.println(number);
number--;
System.out.println(number);
运行结果:
11
10
自增运算符放在变量前面和后面,单独使用时没有区别:
int a = 10;
a++;
int b = 10;
++b;
如果参与表达式计算,执行顺序就不同了。
1. 前置自增
前置自增会先把变量加 1,再使用变量的值。
int number = 10;
int result = ++number;
System.out.println(number);
System.out.println(result);
运行结果:
11
11
2. 后置自增
后置自增会先使用变量原来的值,再把变量加 1。
int number = 10;
int result = number++;
System.out.println(number);
System.out.println(result);
运行结果:
11
10
实际开发中,不建议在一个复杂表达式里使用多个自增或自减运算符,否则代码很难阅读。
七、赋值运算符
最常见的赋值运算符是 =:
int age = 18;
Java 还提供了复合赋值运算符。
| 运算符 | 示例 | 说明 |
|---|---|---|
+= |
a += 2 |
加后赋值 |
-= |
a -= 2 |
减后赋值 |
*= |
a *= 2 |
乘后赋值 |
/= |
a /= 2 |
除后赋值 |
%= |
a %= 2 |
取余后赋值 |
示例:
int number = 10;
number += 5;
System.out.println(number);
number *= 2;
System.out.println(number);
运行结果:
15
30
复合赋值运算符会自动完成一次类型转换:
short number = 10;
number += 1;
上面的代码可以正常编译。
但是下面的代码会编译失败:
short number = 10;
// number = number + 1;
// 编译错误
原因是 short 参与算术运算时会被提升为 int,所以 number + 1 的结果是 int 类型,不能直接赋值给 short。
number += 1 实际上相当于:
number = (short) (number + 1);
八、比较运算符
比较运算符用于比较两个数据,计算结果一定是 boolean 类型。
| 运算符 | 作用 |
|---|---|
== |
判断是否相等 |
!= |
判断是否不相等 |
> |
大于 |
< |
小于 |
>= |
大于或等于 |
<= |
小于或等于 |
示例:
int age = 18;
System.out.println(age == 18);
System.out.println(age != 18);
System.out.println(age > 16);
System.out.println(age <= 20);
运行结果:
true
false
true
true
字符串不能直接使用双等号比较内容
对于基本数据类型,== 比较的是具体数值。
int a = 10;
int b = 10;
System.out.println(a == b);
但是对于引用类型,== 比较的通常是两个变量是否指向同一个对象。
String first = new String("Java");
String second = new String("Java");
System.out.println(first == second);
System.out.println(first.equals(second));
运行结果:
false
true
比较字符串内容时,应使用 equals() 方法:
String language = "Java";
if ("Java".equals(language)) {
System.out.println("内容相同");
}
把确定不为 null 的字符串写在前面,还能避免空指针异常。
九、逻辑运算符
逻辑运算符用于连接多个条件。
| 运算符 | 作用 |
|---|---|
&& |
逻辑与 |
| || | 逻辑或 |
! |
逻辑非 |
1. 逻辑与
&& 两边的条件都为 true,最终结果才是 true。
int age = 20;
boolean hasTicket = true;
boolean canEnter = age >= 18 && hasTicket;
System.out.println(canEnter);
运行结果:
true
2. 逻辑或
|| 两边只要有一个条件为 true,最终结果就是 true。
boolean isMember = false;
boolean hasCoupon = true;
boolean canDiscount = isMember || hasCoupon;
System.out.println(canDiscount);
运行结果:
true
3. 逻辑非
! 用于对布尔值取反。
boolean isLogin = true;
System.out.println(!isLogin);
运行结果:
false
4. 短路运算
&& 和 || 具有短路效果。
使用 && 时,如果左边已经是 false,右边不会继续执行:
int number = 0;
boolean result = number != 0 && 10 / number > 1;
System.out.println(result);
因为 number != 0 是 false,所以右边的除法不会执行,也就不会发生除零异常。
使用 || 时,如果左边已经是 true,右边也不会继续执行。
int age = 20;
boolean result = age >= 18 || age++ > 30;
System.out.println(result);
System.out.println(age);
运行结果:
true
20
由于左边已经是 true,所以右边的 age++ 没有执行。
十、三元运算符
三元运算符适合处理简单的二选一逻辑。
基本格式:
条件 ? 条件成立时的结果 : 条件不成立时的结果
示例:
int age = 20;
String message = age >= 18 ? "成年人" : "未成年人";
System.out.println(message);
还可以用它求两个数字中的较大值:
int a = 10;
int b = 20;
int max = a > b ? a : b;
System.out.println(max);
如果判断逻辑比较复杂,建议使用 if-else,这样代码会更加清晰。
十一、字符串连接运算符
当 + 的一边是字符串时,它的作用就不再是加法,而是拼接字符串。
String name = "张三";
int age = 18;
System.out.println("姓名:" + name);
System.out.println("年龄:" + age);
需要注意表达式的计算顺序:
System.out.println(10 + 20 + "Java");
System.out.println("Java" + 10 + 20);
运行结果:
30Java
Java1020
Java 会按照从左到右的顺序进行计算。
第一行先计算 10 + 20,得到 30,然后再和字符串拼接。
第二行先得到 "Java10",后面的 20 也会继续进行字符串拼接。
如果想先进行加法,可以使用括号:
System.out.println("计算结果:" + (10 + 20));
运行结果:
计算结果:30
十二、运算符优先级
不同运算符的优先级不同。
int result = 10 + 2 * 3;
System.out.println(result);
运行结果:
16
乘法的优先级高于加法,所以先计算 2 * 3。
如果希望先计算加法,可以添加括号:
int result = (10 + 2) * 3;
System.out.println(result);
运行结果:
36
实际编程时,如果一个表达式包含多种运算符,建议使用括号明确计算顺序。这样既方便自己阅读,也能减少理解错误。
十三、自动类型转换
当取值范围较小的数据类型转换为取值范围较大的数据类型时,Java 通常会自动完成转换。
常见的转换方向如下:
byte -> short -> int -> long -> float -> double
char -> int
示例:
int number = 100;
long longNumber = number;
double doubleNumber = longNumber;
System.out.println(doubleNumber);
运行结果:
100.0
完整示例:
byte first = 10;
short second = first;
int third = second;
long fourth = third;
double fifth = fourth;
这种转换不需要手动添加类型,Java 会自动处理。
不过,自动类型转换并不代表绝对不会丢失精度。例如,将特别大的 long 转换为 float 或 double 时,仍然有可能出现精度损失。
十四、表达式中的类型提升
byte、short 和 char 在参与算术运算时,会自动提升为 int 类型。
byte a = 10;
byte b = 20;
int result = a + b;
System.out.println(result);
下面的代码会编译失败:
byte a = 10;
byte b = 20;
// byte result = a + b;
// 编译错误,a + b 的结果是 int
不同类型的数据一起运算时,结果通常会向取值范围更大的类型提升。
int quantity = 3;
double price = 19.9;
double total = quantity * price;
System.out.println(total);
运行结果:
59.699999999999996
这里也能看出浮点数存在精度问题。如果计算的是实际金额,应该使用 BigDecimal。
十五、强制类型转换
当取值范围较大的类型转换为取值范围较小的类型时,需要使用强制类型转换。
基本格式:
目标类型 变量名 = (目标类型) 原始数据;
示例:
double price = 19.99;
int result = (int) price;
System.out.println(result);
运行结果:
19
浮点数强制转换为整数时,小数部分会被直接舍弃,并不会进行四舍五入。
如果需要四舍五入,可以使用 Math.round():
double number = 19.99;
long result = Math.round(number);
System.out.println(result);
运行结果:
20
强制类型转换可能导致数据溢出
看下面的例子:
int number = 130;
byte result = (byte) number;
System.out.println(result);
运行结果:
-126
byte 的取值范围是 -128 到 127,而 130 已经超出了这个范围,因此转换后的结果不是原来的数值。
所以,强制类型转换虽然能够通过编译,但不代表转换结果一定正确。
十六、字符串和基本类型之间的转换
实际开发中,从控制台、前端页面或配置文件中读取到的数据经常是字符串,因此需要掌握字符串和基本类型之间的转换。
1. 基本类型转换为字符串
可以使用 String.valueOf():
int age = 18;
String ageText = String.valueOf(age);
System.out.println(ageText);
也可以通过字符串拼接完成:
int age = 18;
String ageText = age + "";
两种方式都能实现转换,不过 String.valueOf() 的含义更加明确。
2. 字符串转换为整数
使用 Integer.parseInt():
String text = "100";
int number = Integer.parseInt(text);
System.out.println(number + 20);
运行结果:
120
3. 字符串转换为其他基本类型
long longNumber = Long.parseLong("1000");
double price = Double.parseDouble("19.99");
float score = Float.parseFloat("95.5");
boolean result = Boolean.parseBoolean("true");
如果字符串不是合法的数字格式,程序会出现异常:
String text = "Java";
// int number = Integer.parseInt(text);
// 运行时出现 NumberFormatException
可以使用 try-catch 处理这种情况:
String text = "Java";
try {
int number = Integer.parseInt(text);
System.out.println(number);
} catch (NumberFormatException exception) {
System.out.println("输入的内容不是有效整数");
}
十七、综合案例
下面通过一个简单的商品结算程序,把变量、数据类型、运算符和类型转换结合起来。
public class OrderDemo {
public static void main(String[] args) {
String productName = "Java 入门教程";
double unitPrice = 69.8;
int quantity = 3;
double discount = 0.9;
double originalPrice = unitPrice * quantity;
double finalPrice = originalPrice * discount;
boolean freeShipping = finalPrice >= 99;
System.out.println("商品名称:" + productName);
System.out.println("购买数量:" + quantity);
System.out.println("商品原价:" + originalPrice);
System.out.println("优惠价格:" + finalPrice);
System.out.println("是否包邮:" + (freeShipping ? "是" : "否"));
}
}
运行结果:
商品名称:Java 入门教程
购买数量:3
商品原价:209.39999999999998
优惠价格:188.45999999999998
是否包邮:是
由于 double 存在精度问题,商品金额更适合使用 BigDecimal。
import java.math.BigDecimal;
import java.math.RoundingMode;
public class OrderDemo {
public static void main(String[] args) {
String productName = "Java 入门教程";
BigDecimal unitPrice = new BigDecimal("69.8");
BigDecimal quantity = new BigDecimal("3");
BigDecimal discount = new BigDecimal("0.9");
BigDecimal originalPrice = unitPrice.multiply(quantity);
BigDecimal finalPrice = originalPrice
.multiply(discount)
.setScale(2, RoundingMode.HALF_UP);
boolean freeShipping =
finalPrice.compareTo(new BigDecimal("99")) >= 0;
System.out.println("商品名称:" + productName);
System.out.println("商品原价:" + originalPrice);
System.out.println("优惠价格:" + finalPrice);
System.out.println("是否包邮:" + (freeShipping ? "是" : "否"));
}
}
运行结果:
商品名称:Java 入门教程
商品原价:209.4
优惠价格:188.46
是否包邮:是
十八、常见问题
1. 为什么两个整数相除没有小数
因为整数和整数运算,结果仍然是整数。
double result = 10 / 3;
System.out.println(result);
虽然接收结果的是 double,但是 10 / 3 已经先完成了整数运算,所以结果是 3,最后才转换成 3.0。
正确写法:
double result = 10.0 / 3;
或者:
double result = (double) 10 / 3;
2. 为什么两个 byte 相加不能赋值给 byte
因为 byte、short 和 char 参与算术运算时,会自动提升为 int。
byte a = 10;
byte b = 20;
int result = a + b;
3. 为什么不能使用双等号比较字符串内容
== 比较的是两个引用是否指向同一个对象,equals() 比较的才是字符串内容。
String first = new String("Java");
String second = new String("Java");
System.out.println(first.equals(second));