数据类型、变量、类型转换、运算符以及程序逻辑控制
数据类型
基本数据类型
| 关键字 | 字节 | 范围(十进制) | 范围(描述) | 包装类 | 说明 | 示例 |
|---|---|---|---|---|---|---|
| int | 4字节 | -2,147,483,648 ~ 2,147,483,647 | [Integer.MIN_VALUE, Integer.MAX_VALUE] | Integer | 32位有符号整数,默认整型 | int a = 100; |
| short | 2字节 | -32,768 ~ 32,767 | [Short.MIN_VALUE, Short.MAX_VALUE] | Short | 16位有符号整数 | short s = 1000; |
| long | 8字节 | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 | [Long.MIN_VALUE, Long.MAX_VALUE] | Long | 64位有符号整数,字面值加L | long l = 100000L; |
| byte | 1字节 | -128 ~ 127 | [Byte.MIN_VALUE, Byte.MAX_VALUE] | Byte | 8位有符号整数 | byte b = 100; |
| double | 8字节 | ±4.9E-324 ~ ±1.8E+308 | 约15-16位有效数字 | Double | 双精度浮点数,默认浮点型 | double d = 3.14159; double d2 = 3.14d; |
| float | 4字节 | ±1.4E-45 ~ ±3.4E+38 | 约6-7位有效数字 | Float | 单精度浮点数,字面值加F | float f = 3.14f; |
| char | 2字节 | 0 ~ 65,535 | Unicode: U+0000 ~ U+FFFF | Character | 16位无符号Unicode字符 | char c = 'A'; char c2 = '\u0041'; |
| boolean | 未明确规定 | true 或 false | 只有两个值 | Boolean | 布尔值,不能与数字相互转换 | boolean flag = true; boolean isValid = false; |
引用数据类型
| 类型 | 关键字/语法 | 存储内容 | 默认值 | 示例 |
|---|---|---|---|---|
| 字符串 | String |
Unicode字符序列 | null |
String s = "Hello"; |
| 类 | class |
对象实例 | null |
Person p = new Person(); |
| 接口 | interface |
实现类的实例 | null |
List<String> list = new ArrayList<>(); |
| 数组 | [] |
同类型元素集合 | null |
int[] arr = {1, 2, 3}; |
| 枚举 | enum |
预定义常量集合 | null |
Day day = Day.MONDAY; |
| 注解 | @interface |
元数据 | null |
@Override |
变量
浮点型要点
int/int与double/double
java
int a = 1;
int b = 2;
System.out.println(a / b); // 输出 0,不是 0.5
double a = 1.0;
double b = 2.0;
System.out.println(a / b); // 输出0.5
-
当两个
int类型的数进行除法运算时,结果仍然是int类型 -
Java 会进行整数除法,直接截断小数部分(不是四舍五入)
-
当两个
double类型的数进行除法运算时,结果是double类型 -
Java 会进行浮点数除法,保留小数部分
如果想要 int 类型相除得到小数结果,有以下几种方法:
java
// 方法1:强制类型转换
System.out.println((double) a / b); // 输出 0.5
// 方法2:使用浮点数表示
System.out.println(a / 2.0); // 输出 0.5
// 方法3:乘以 1.0 转换为浮点数
System.out.println(a * 1.0 / b); // 输出 0.5
浮点数只是近似值
java
// 示例1:简单的小数运算
System.out.println(0.1 + 0.2); // 输出:0.30000000000000004,不是 0.3
// 示例2:十进制小数的二进制表示问题
System.out.println(0.1 + 0.1 + 0.1); // 输出:0.30000000000000004
// 示例3:大数和小数的运算
double large = 1.0e20;
double small = 1.0;
System.out.println(large + small - large); // 输出:0.0(精度丢失)
- 十进制小数(如 0.1)在二进制中是循环小数(类似 1/3 在十进制中是 0.333...)
什么时候需要特别注意?
java
// 避免直接比较浮点数是否相等
double a = 0.1 + 0.2;
double b = 0.3;
System.out.println(a == b); // false!错误方式
// 正确的比较方式:使用容差范围
double epsilon = 1e-10;
System.out.println(Math.abs(a - b) < epsilon); // true
需要精确计算的场景:
java
// 使用 BigDecimal(大数运算)
import java.math.BigDecimal;
BigDecimal d1 = new BigDecimal("0.1");
BigDecimal d2 = new BigDecimal("0.2");
System.out.println(d1.add(d2)); // 输出精确的 0.3
// 但要注意构造函数的区别
BigDecimal wrong = new BigDecimal(0.1); // 已经是不精确的 double
BigDecimal right = new BigDecimal("0.1"); // 使用字符串构造
字符型要点
字符型编码
java
char ch = 'A';
char ch2 = '中'; // 中文字符
char ch3 = '😊'; // 表情符号(这是一个补充字符)
System.out.println("char 大小(字节): " + Character.BYTES); // 输出 2
System.out.println("char 位数: " + Character.SIZE); // 输出 16
- Java 使用 UTF-16 编码表示字符(早期设计时称为 "Unicode 字符")
- 一个
char可以表示 Unicode 基本多文种平面(BMP)中的字符,范围是 U+0000 到 U+FFFF - 这需要 16 位,即 2 个字节
布尔型要点
boolean 的严格类型检查
- Java 的
boolean和int是互不兼容的类型 - 不能 用 1 表示 true,0 表示 false
- 不能 在条件语句中使用非布尔表达式
java
// ========== 错误用法(编译错误)==========
// 1. 不能用数字赋值给boolean
boolean b1 = 1; // 错误!不能将int转换为boolean
boolean b2 = 0; // 错误!
// 2. 条件语句必须用boolean
int x = 10;
if (x) { // 错误!条件必须是boolean类型
System.out.println("x is true");
}
// 3. 不能将boolean转换为int
boolean flag = true;
int num = flag; // 错误!不能将boolean转换为int
int num2 = flag ? 1 : 0; // 这是正确的(三元表达式返回int)
// ========== 正确用法 ==========
// 1. 只能使用true/false
boolean b3 = true; // 正确
boolean b4 = false; // 正确
// 2. 条件必须是boolean表达式
int x = 10;
if (x > 5) { // 正确:比较表达式返回boolean
System.out.println("x > 5");
}
// 3. 需要转换时使用显式逻辑
boolean flag = true;
// 将boolean转换为int
int num = flag ? 1 : 0; // 正确:使用三元运算符
int num2 = flag ? 100 : 200; // 正确:可以指定任意值
// 将int转换为boolean(需要显式比较)
int value = 1;
boolean isTrue = (value != 0); // 正确:通过比较得到boolean
boolean isOne = (value == 1); // 正确
类型提升和转换
自动类型提升(隐式)
自动类型转换即:代码不需要经过任何处理,在代码编译时,编译器会自动进行处理。
特点:数据范围小的转为数据范围大的时会自动进行。
byte → short → int → long → float → double
↑
char
java
// ✅ 正确的自动转换(小→大)
byte b = 10; // byte范围: -128~127
short s = b; // byte → short ✓
int i = s; // short → int ✓
long l = i; // int → long ✓
// ❌ 错误的转换(大→小,需要强制转换)
// long l2 = 100L;
// int i2 = l2; // 编译错误:long → int
int i2 = (int)l2; // 需要强制类型转换
java
// 1. int 和 long 运算
int a = 10;
long b = 20L;
long result1 = a + b; // a自动提升为long
// 2. byte 和 byte 运算
byte x = 10;
byte y = 20;
int result2 = x + y; // byte运算自动提升为int
// 问题:下面的输出是什么?
byte x1 = 10;
byte y1 = 20;
// byte c1 = x1 + y1; // 编译错误
byte c1 = (byte)(x1 + y1); // ✅ 需要强转
// 3. float 和 double 运算
float f = 3.14F;
double d = 2.5;
double result3 = f + d; // f自动提升为double
强制类型转换(显式)
特点:数据范围大的到数据范围小的。
java
// 示例1:整数截断
int num = 300;
byte b = (byte)num; // 结果为44,发生溢出
// 示例2:浮点数转整数
double d = 3.99;
int i = (int)d; // 结果为3,小数部分被截断
// 示例3:大整数转小整数
long bigNum = 1234567890123L;
int smallNum = (int)bigNum; // 可能得到意外结果
java
boolean flag = true;
// int num = flag; // ❌ 编译错误,不能转换
// flag = (boolean)1; // ❌ 编译错误,不能转换
// 只有数值类型之间可以相互转换
// 引用类型的转换需要继承关系
字符串转换方法
| 目标类型 | 转换方法 | 示例 |
|---|---|---|
String → int |
Integer.parseInt() |
int i = Integer.parseInt("123"); |
String → double |
Double.parseDouble() |
double d = Double.parseDouble("3.14"); |
String → boolean |
Boolean.parseBoolean() |
boolean b = Boolean.parseBoolean("true"); |
任意 → String |
①String.valueOf() ②String str = num + ""; |
String s = String.valueOf(123); |
运算符
运算符完整总结表
| 类别 | 运算符 | 名称 | 说明 | 示例 | 结果 | 优先级 | 结合性 |
|---|---|---|---|---|---|---|---|
| 算术运算符 | + |
加法 | 数值相加或字符串连接 | 5 + 3 "Hello" + "World" |
8 "HelloWorld" |
4 | 左→右 |
- |
减法 | 数值相减 | 10 - 4 |
6 |
4 | 左→右 | |
* |
乘法 | 数值相乘 | 3 * 4 |
12 |
3 | 左→右 | |
/ |
除法 | 整数除法或浮点数除法 | 10 / 3 10.0 / 3 |
3 3.333... |
3 | 左→右 | |
% |
取模 | 求余数 | 10 % 3 |
1 |
3 | 左→右 | |
++ |
自增 | 前/后自增 | a=5; b=++a a=5; b=a++ |
a=6, b=6 a=6, b=5 |
2 | 右→左 | |
-- |
自减 | 前/后自减 | a=5; b=--a a=5; b=a-- |
a=4, b=4 a=4, b=5 |
2 | 右→左 | |
| 关系运算符 | > |
大于 | 比较大小 | 5 > 3 |
true |
6 | 左→右 |
< |
小于 | 比较大小 | 3 < 5 |
true |
6 | 左→右 | |
>= |
大于等于 | 比较大小 | 5 >= 5 |
true |
6 | 左→右 | |
<= |
小于等于 | 比较大小 | 3 <= 5 |
true |
6 | 左→右 | |
== |
等于 | 值相等判断 | 5 == 5 |
true |
7 | 左→右 | |
!= |
不等于 | 值不相等判断 | 5 != 3 |
true |
7 | 左→右 | |
| 逻辑运算符 | && |
逻辑与 | 短路与,全真为真 | true && false |
false |
11 | 左→右 |
| ` | ` | 逻辑或 | 短路或,一真即真 | `true | |||
! |
逻辑非 | 取反 | !true |
false |
2 | 右→左 | |
& |
逻辑与 | 非短路与 | true & false |
false |
8 | 左→右 | |
| ` | ` | 逻辑或 | 非短路或 | `true | false` | true |
|
^ |
逻辑异或 | 相同为假,不同为真 | true ^ false |
true |
9 | 左→右 | |
| 位运算符 | & |
按位与 | 二进制位与运算 | 5 & 3 (101 & 011) |
1 (001) |
8 | 左→右 |
| ` | ` | 按位或 | 二进制位或运算 | `5 | 3` (101 | 011) | 7 (111) |
|
^ |
按位异或 | 二进制位异或 | 5 ^ 3 (101 ^ 011) |
6 (110) |
9 | 左→右 | |
~ |
按位取反 | 二进制位取反 | ~5 |
-6 |
2 | 右→左 | |
<< |
左移位 | 左移指定位数 | 5 << 1 (101左移1位) |
10 (1010) |
5 | 左→右 | |
>> |
右移位 | 带符号右移 | -5 >> 1 |
-3 |
5 | 左→右 | |
>>> |
无符号右移 | 高位补0右移 | -5 >>> 1 |
2147483645 |
5 | 左→右 | |
| 赋值运算符 | = |
赋值 | 将右值赋给左值 | a = 5 |
a = 5 |
14 | 右→左 |
+= |
加赋值 | a = a + b |
a += 3 |
a = a + 3 |
14 | 右→左 | |
-= |
减赋值 | a = a - b |
a -= 3 |
a = a - 3 |
14 | 右→左 | |
*= |
乘赋值 | a = a * b |
a *= 3 |
a = a * 3 |
14 | 右→左 | |
/= |
除赋值 | a = a / b |
a /= 3 |
a = a / 3 |
14 | 右→左 | |
%= |
取模赋值 | a = a % b |
a %= 3 |
a = a % 3 |
14 | 右→左 | |
&= |
与赋值 | a = a & b |
a &= 3 |
a = a & 3 |
14 | 右→左 | |
| ` | =` | 或赋值 | `a = a | b` | `a | = 3` | |
^= |
异或赋值 | a = a ^ b |
a ^= 3 |
a = a ^ 3 |
14 | 右→左 | |
<<= |
左移赋值 | a = a << b |
a <<= 1 |
a = a << 1 |
14 | 右→左 | |
>>= |
右移赋值 | a = a >> b |
a >>= 1 |
a = a >> 1 |
14 | 右→左 | |
>>>= |
无符号右移赋值 | a = a >>> b |
a >>>= 1 |
a = a >>> 1 |
14 | 右→左 | |
| 三元运算符 | ? : |
条件运算符 | 根据条件选择值 | a > b ? a : b |
较大值 | 13 | 右→左 |
| 类型运算符 | instanceof |
实例判断 | 判断对象类型 | obj instanceof String |
true/false |
6 | 左→右 |
| 其他 | () |
括号 | 改变运算顺序 | (a + b) * c |
先加后乘 | 1 | 左→右 |
[] |
下标 | 数组访问 | arr[0] |
数组第一个元素 | 1 | 左→右 | |
. |
成员访问 | 访问对象成员 | obj.method() |
调用方法 | 1 | 左→右 |
优先级从高到低总结(数字越小优先级越高):
()[].!~++--(一元)*/%+-<<>>>>><<=>>=instanceof==!=&^|&&||? :=+=-=*=/=%=&=|=^=<<=>>=>>>=
程序逻辑控制
顺序结构
分支结构
| 类型 | 语法结构 | 适用场景 | 特点 | 执行流程 | 注意事项 |
|---|---|---|---|---|---|
| if单分支 | if (条件表达式) { // 语句块} |
单一条件判断 | 条件为true时执行代码块 | 检查条件 → true执行 → 结束 | 条件必须是布尔表达式 |
| if-else双分支 | if (条件表达式) { // 语句块1} else { // 语句块2} |
二选一执行 | 两个互斥的分支 | 检查条件 → true执行块1 / false执行块2 | else必须与if配对使用 |
| if-else if-else多分支 | if (条件1) { // 语句块1} else if (条件2) { // 语句块2} else { // 语句块3} |
多条件判断 | 多个互斥条件,顺序检查 | 按顺序检查条件 → 第一个true执行对应块 → 结束 | 条件顺序影响结果 |
| 嵌套if | if (条件1) { if (条件2) { // 语句块<br> }} |
复杂条件判断 | 在if内部再包含if | 外层条件通过 → 检查内层条件 → 执行 | 避免嵌套过深(不超过3层) |
| switch-case | switch (表达式) { case 值1: // 语句块1 break; case 值2: // 语句块2 break; default: // 默认语句块} |
等值比较的多分支 | 基于表达式的值选择分支 | 计算表达式 → 匹配case → 执行对应块 → break跳出 | 1. 表达式类型有限制 2. 注意case穿透 3. 必须有break |
| switch-case(无break) | switch (表达式) { case 值1: case 值2: // 共享语句块 break;} |
多个值共享相同逻辑 | 利用case穿透特性 | 匹配任一case → 向下执行直到break | 有意使用case穿透时,要写清楚注释 |
| 三元运算符 | 条件 ? 表达式1 : 表达式2 |
简单的二选一赋值 | if-else的简写形式 | 计算条件 → true返回表达式1 / false返回表达式2 | 1. 必须有返回值 2. 表达式类型要兼容 |
switch表达式支持的类型
| 数据类型 | 支持版本 | 示例 |
|---|---|---|
byte |
所有版本 | switch (b) |
short |
所有版本 | switch (s) |
int |
所有版本 | switch (i) |
char |
所有版本 | switch (ch) |
String |
Java 7+ | switch (str) |
enum |
Java 5+ | switch (color) |
| 包装类 | Java 5+(自动拆箱) | switch (integer) |
- 注意不能是
long类型
循环结构
循环结构对比总表
| 循环类型 | 语法格式 | 执行顺序 | 特点 | 适用场景 | 示例 |
|---|---|---|---|---|---|
| for循环 | for (初始化; 条件; 更新) {<br> // 循环体<br>}<br> |
初始化 → 条件判断 → 循环体 → 更新 → 条件判断... | 1. 循环次数明确 2. 结构清晰 3. 变量作用域在循环内 | 已知循环次数 数组/集合遍历 固定次数的操作 | for (int i=0; i<5; i++) {<br> System.out.println(i);<br>}<br> |
| while循环 | while (条件表达式) {<br> // 循环体<br>}<br> |
条件判断 → 循环体 → 条件判断... | 1. 先判断后执行 2. 可能一次都不执行 3. 适合条件复杂的情况 | 循环次数不确定 条件驱动循环 读取流/用户输入 | int i=0;<br>while (i<5) {<br> System.out.println(i);<br> i++;<br>}<br> |
| do-while循环 | do {<br> // 循环体<br>} while (条件表达式);<br> |
循环体 → 条件判断 → 循环体... | 1. 先执行后判断 2. 至少执行一次 3. 末尾有分号 | 至少执行一次 输入验证 菜单显示 | int i=0;<br>do {<br> System.out.println(i);<br> i++;<br>} while (i<5);<br> |
| 增强for循环 (foreach) | for (类型 变量 : 集合/数组) {<br> // 循环体<br>}<br> |
遍历集合/数组每个元素 | 1. 简化遍历语法 2. 只读遍历 3. 不能获取索引 | 遍历数组/集合 不需要修改元素 不需要索引 | int[] arr = {1,2,3};<br>for (int num : arr) {<br> System.out.println(num);<br>}<br> |
输入输出
输出到控制台
java
System.out.println(msg); // 输出一个字符串, 带换行
System.out.print(msg); // 输出一个字符串, 不带换行
System.out.printf(format, msg); // 格式化输出
| 转换符 | 类型 | 举例 | 结果 |
|---|---|---|---|
| d | 十进制整数 | ("%d", 100) | 100 |
| x | 十六进制整数 | ("%x", 100) | 64 |
| o | 八进制整数 | ("%o", 100) | 144 |
| f | 定点浮点数 | ("%f", 100f) | 100.000000 |
| e | 指数浮点数 | ("%e", 100f) | 1.000000e+02 |
| g | 通用浮点数 | ("%g", 100f) | 100.000 |
| a | 十六进制浮点数 | ("%a", 100) | 0x1.9p6 |
| s | 字符串 | ("%s", 100) | 100 |
| c | 字符 | ("%c", '1') | 1 |
| b | 布尔值 | ("%b", 100) | true |
| h | 散列码 | ("%h", 100) | 64 |
| % | 百分号 | ("%.2f%%", 2/7f) | 0.29% |
从键盘输入
java
import java.util.Scanner; // 需要导入 util 包
Scanner sc = new Scanner(System.in);
System.out.println("请输入你的姓名:");
String name = sc.nextLine();
System.out.println("请输入你的年龄:");
int age = sc.nextInt();
System.out.println("请输入你的工资:");
float salary = sc.nextFloat();
System.out.println("你的信息如下:");
System.out.println("姓名: "+name+"\n"+"年龄:"+age+"\n"+"工资:"+salary);
sc.close(); // 注意, 要记得调用关闭方法
java
//多个输入,使用 ctrl + z 来结束输入 (Linux / Mac 上使用 ctrl+ d)
Scanner sc = new Scanner(System.in);
int sum = 0;
int num = 0;
while (sc.hasNextInt()) {
int tmp = sc.nextInt();
sum += tmp;
num++;
}
System.out.println("sum = " + sum);
System.out.println("avg = " + sum / num);
sc.close();