Java 变量、基本数据类型与类型转换
变量是数据的"容器",数据类型决定容器"装什么、装多大、怎么算"。
8 种基本类型是 Java 一切计算的基石;类型转换是写代码时最容易翻车、最隐蔽出 bug 的地方。
一、变量(Variable)
1.1 什么是变量
变量就是内存中的一块命名存储空间,用来保存程序运行中会变化的数据。它是一个"三要素"的组合:
| 要素 | 含义 | 示例 |
|---|---|---|
| 类型 | 决定存什么、占多大空间 | int 占 4 字节 |
| 名称 | 通过名字访问这块空间 | age |
| 值 | 空间里实际存的数据 | 18 |
int age = 18; // 类型 int + 名称 age + 值 18
本质:
int age = 18;这句话做了三件事——在内存中开辟一块 4 字节空间、给空间起名age、往空间里写入 18。之后age = 20;是"改写这块空间的值",而不是"把 age 重新指向别处"(变量不像引用,它本身不"指向",它就是这块空间)。
1.2 变量的使用:三步走
// 第 1 步:声明(只定类型和名字,不赋值)
int age;
// 第 2 步:赋值(把值写进空间)
age = 18;
// 第 3 步:使用(读取 / 参与运算)
System.out.println(age); // 读取
int next = age + 1; // 参与运算
// 也可以声明 + 赋值一步到位
int score = 100;
1.3 变量的分类
| 分类维度 | 类型 | 说明 |
|---|---|---|
| 按声明位置 | 局部变量 | 方法内部声明,必须初始化才能用,无默认值 |
| 按声明位置 | 成员变量(实例变量/字段) | 类内、方法外,有默认值 |
| 按修饰符 | 静态变量(类变量) | static 修饰,类加载即存在,全类共享 |
| 按数据类型 | 基本类型变量 | 存值本身 |
| 按数据类型 | 引用类型变量 | 存对象的"地址"(如 String、数组、对象) |
二、Java 基本数据类型(8 种)
Java 是强类型语言:每个变量必须先声明类型,且类型一旦确定不可更改。基本数据类型(primitive type)共 8 种,分四大类:
2.1 整数型(byte / short / int / long)
| 类型 | 占用字节 | 取值范围 | 包装类 |
|---|---|---|---|
byte |
1 字节(8 位) | -128 ~ 127(-2⁷ ~ 2⁷-1) | Byte |
short |
2 字节(16 位) | -32768 ~ 32767(-2¹⁵ ~ 2¹⁵-1) | Short |
int |
4 字节(32 位) | -2³¹ ~ 2³¹-1(约 ±21 亿) | Integer |
long |
8 字节(64 位) | -2⁶³ ~ 2⁶³-1 | Long |
byte b = 127; // ✅ 最大 127
byte b2 = 128; // ❌ 编译报错:超出范围
int i = 2100000000; // ✅ 约 21 亿
long l = 3000000000L; // ✅ 超过 int 范围,必须加 L
long l2 = 3000000000; // ❌ 编译报错:整数默认是 int,3000000000 已超 int 范围
2.2 浮点型(float / double)
| 类型 | 占用字节 | 精度 | 包装类 |
|---|---|---|---|
float |
4 字节 | 单精度,约 6~7 位有效数字 | Float |
double |
8 字节 | 双精度,约 15~16 位有效数字 | Double |
double d = 3.14; // ✅ 浮点数默认是 double
float f = 3.14F; // ✅ 必须加 F/f
float f2 = 3.14; // ❌ 编译报错:3.14 默认是 double,double 不能自动降为 float
2.3 字符型(char)—— 详见第五节
| 类型 | 占用字节 | 取值范围 | 包装类 |
|---|---|---|---|
char |
2 字节(16 位) | 0 ~ 65535(Unicode) | Character |
2.4 布尔型(boolean)
| 类型 | 占用 | 取值 | 包装类 |
|---|---|---|---|
boolean |
1 字节(JVM 内部实现,规范未明确规定位数) | 只有 true / false |
Boolean |
boolean flag = true;
boolean isOk = false;
// boolean b = 1; // ❌ 不能用 0/1 表示,与 C/C++ 不同
2.5 8 种基本类型总表
| 类型 | 大小 | 默认值 | 取值范围 | 包装类 |
|---|---|---|---|---|
byte |
1 字节 | 0 |
-128 ~ 127 | Byte |
short |
2 字节 | 0 |
-32768 ~ 32767 | Short |
int |
4 字节 | 0 |
-2³¹ ~ 2³¹-1 | Integer |
long |
8 字节 | 0L |
-2⁶³ ~ 2⁶³-1 | Long |
float |
4 字节 | 0.0f |
IEEE 754 单精度 | Float |
double |
8 字节 | 0.0d |
IEEE 754 双精度 | Double |
char |
2 字节 | '�' |
0 ~ 65535 | Character |
boolean |
1 字节 | false |
true / false |
Boolean |
关键区分:上表中的"默认值"指的是成员变量(类字段)的默认值。局部变量没有默认值,不初始化就使用会编译报错。
三、类型定义(字面量的默认类型)
这一节是新手最容易踩坑的地方:你在代码里写的"数字"本身也有类型,Java 对字面量有一组默认规则。
| 字面量 | 默认类型 | 规则 |
|---|---|---|
整数(如 100、21) |
int |
整数默认 int |
浮点数(如 3.14) |
double |
小数默认 double |
long 字面量 |
加后缀 L/l |
推荐大写 L(小写 l 像数字 1) |
float 字面量 |
加后缀 F/f |
必须加 |
| 十六进制 | 0x 开头 |
如 0x1F = 31 |
| 八进制 | 0 开头 |
如 017 = 15(易混淆,少用) |
| 二进制 | 0b 开头 |
如 0b1010 = 10 |
| 下划线分隔 | 1_000_000 |
数字中间可加 _,增强可读性 |
long l1 = 100L; // ✅ 明确 long
long l2 = 100; // ✅ 100 是 int,会自动转 long(安全)
long l3 = 100_000_000_000L; // ✅ 超过 int 范围,必须 L
float f1 = 3.14f; // ✅
double d1 = 3.14; // ✅ 默认就是 double
double d2 = 3.14d; // ✅ 加 d 也合法,但没必要
int hex = 0xFF; // 255
int bin = 0b1111; // 15
一句话口诀:整数默认 int,小数默认 double;long 加 L,float 加 F。
四、变量注意点(高频易错)
-
先声明,后使用:Java 不声明类型无法定义变量。
a = 10; // ❌ a 未声明 int a = 10; // ✅ -
局部变量必须初始化:不赋初值就使用会编译报错(和成员变量不同)。
int x; // 局部变量,未初始化 System.out.println(x); // ❌ 编译报错:可能尚未初始化变量 x -
变量不能重复声明(同一作用域内同名)。
int a = 1; int a = 2; // ❌ 重复声明 -
变量有作用域:从声明处开始,到所在
{}块结束。{ int a = 1; } // System.out.println(a); // ❌ 出了 {} 作用域,a 已失效 -
类型一旦确定不可更改:不能把
int变量再赋成字符串。int a = 1; // a = "hello"; // ❌ 类型不匹配 -
一行可声明多个同类型变量(但不推荐混不同类型)。
int a = 1, b = 2, c = 3; // ✅ // int a = 1, String s = "x"; // ❌ 类型不同不能同行声明 -
警惕浮点精度陷阱:
float/double是近似值,不能用==判断两个浮点数相等。System.out.println(0.1 + 0.2); // 输出 0.30000000000000004 System.out.println(0.1 + 0.2 == 0.3); // false ❗ // 金融金额计算请用 BigDecimal,不要用 double -
整数除法:两个
int相除,结果仍是int,会截断小数。System.out.println(5 / 2); // 2,不是 2.5! System.out.println(5.0 / 2); // 2.5,有 double 参与就得到 double
五、字符类型(char)
5.1 基本概念
char 是 Java 中唯一的字符类型,占 2 字节,底层用 Unicode 编码,取值范围 0 ~ 65535(对应 Unicode 的 U+0000 ~ U+FFFF)。因为 Java 的 char 采用 UTF-16,所以它能直接表示一个 Unicode 字符(中文、日文、emoji 等基本平面字符都行)。
char c1 = 'A'; // ✅ 单字符,用单引号
char c2 = '中'; // ✅ 中文
char c3 = ' '; // ✅ 空格也是字符
// char c4 = "A"; // ❌ 双引号是字符串 String,不是 char
// char c5 = 'AB'; // ❌ 只能放单个字符
5.2 char 的三种写法
| 写法 | 说明 | 示例 |
|---|---|---|
| 直接字符 | 单个字符用单引号 | 'A' |
| Unicode 值 | \u + 4 位十六进制 |
'A' = 'A' |
| 转义字符 | 特殊控制字符 | '\n'、'\t' |
常用转义字符:
| 转义符 | 含义 | 转义符 | 含义 |
|---|---|---|---|
\n |
换行 | \r |
回车 |
\t |
制表符(Tab) | \\ |
反斜杠 |
\' |
单引号 | \" |
双引号 |
System.out.println("a\nb"); // 输出两行 a 和 b
System.out.println("a\tb"); // 输出 a b(中间是 Tab)
char quote = '\''; // 单引号本身
char backslash = '\\'; // 反斜杠本身
5.3 char 的本质是"整数"
char 底层存的就是 Unicode 码点(一个整数),所以它可以参与整数运算:
char c = 'A';
System.out.println(c + 0); // 65,即 'A' 的 Unicode 值
System.out.println(c + 1); // 66
char d = (char)(c + 1); // 强转回 char,得到 'B'
char z = 'A' + 25; // 'A'(65) + 25 = 90 = 'Z' ✅ 编译期常量可直接赋给 char
注意:
char参与运算时会被自动提升为int,运算结果默认是int,想存回char需要强转(见第六节)。
5.4 char vs String(极易混淆)
char |
String |
|
|---|---|---|
| 本质 | 基本类型(值类型) | 引用类型(类) |
| 引号 | 单引号 'A' |
双引号 "A" |
| 长度 | 固定 1 个字符 | 0 到多个字符 |
| 默认值(成员变量) | '�' |
null |
| 首字母 | 小写 c |
大写 S |
六、基本数据类型转换
类型转换分两种:自动类型转换(隐式)和强制类型转换(显式)。核心原则一句话:小范围 → 大范围自动转,大范围 → 小范围要强转。
6.1 自动类型转换(隐式转换)
当小范围类型的值赋给大范围类型时,自动发生,无需任何代码。范围从大到小排序:
byte → short → int → long → float → double
↑
char
int i = 100;
long l = i; // ✅ int → long 自动转
double d = i; // ✅ int → double 自动转
float f = 100; // ✅ int → float 自动转(int 字面量 100)
char c = 'A';
int n = c; // ✅ char → int 自动转,n = 65
long lg = c; // ✅ char → long 自动转
易忽略点:
long(8 字节整数)能自动转成float(4 字节浮点),虽然float字节数更少,但浮点数的表示范围比整数大,所以允许。转换顺序是看表示范围,不是单纯看字节数。
6.2 强制类型转换(显式转换)
当大范围类型的值赋给小范围类型时,必须手动强转,语法是 (目标类型)。强转可能造成精度丢失或数据溢出,责任由程序员承担。
double d = 3.99;
int i = (int) d; // ✅ 强转,i = 3(小数部分被截断,不是四舍五入!)
long l = 100L;
int n = (int) l; // ✅ long → int 强转
float f = 3.14f;
int m = (int) f; // 3,同样截断
6.3 转换的四个核心细节
① 整数强转可能溢出(高位截断)
int i = 200;
byte b = (byte) i; // 结果不是 200,而是 -56!
// 200 的二进制 0000...1100 1000,截成 8 位得 1100 1000,最高位是符号位 → 负数
② 浮点转整数是"截断"而非"四舍五入"
System.out.println((int) 3.99); // 3,不是 4
System.out.println((int) -3.99); // -3,向 0 截断
③ byte / short / char 参与运算时,自动提升为 int
byte b1 = 10;
byte b2 = 20;
// byte b3 = b1 + b2; // ❌ 编译报错:b1 + b2 结果是 int
int b3 = b1 + b2; // ✅
byte b4 = (byte)(b1 + b2); // ✅ 强转回去
这是新手最常见编译错误:两个 byte 相加,结果是 int,不能直接赋回 byte。
④ boolean 不参与任何类型转换
// int x = (int) true; // ❌ boolean 不能和其他类型互转
// boolean b = 1; // ❌
6.4 字符串 String 与基本类型的转换(补充)
String 是引用类型,但实际开发中与基本类型互转极常见:
// 基本类型 → String
String s1 = 100 + ""; // 拼接空串
String s2 = String.valueOf(100); // 推荐
String s3 = Integer.toString(100);
// String → 基本类型(用包装类)
int i = Integer.parseInt("100");
double d = Double.parseDouble("3.14");
boolean b = Boolean.parseBoolean("true");
// 易错:字符串拼接与数值相加的优先级
System.out.println("a" + 1 + 2); // a12(从左到右,先拼 "a1",再拼 2)
System.out.println(1 + 2 + "a"); // 3a(先算 1+2=3,再拼 "a")
七、总结
1. 概念三条线:
- 变量 = 类型 + 名称 + 值,是内存中的命名空间;局部变量必须初始化,成员变量有默认值。
- 8 种基本类型 = 4 整型(
byte/short/int/long)+ 2 浮点(float/double)+ 1 字符(char)+ 1 布尔(boolean)。 - 类型转换 = 自动(小→大)与强制(大→小,会丢精度/溢出)。
2. 记忆口诀:
- 类型定义:整数默认
int,小数默认double,long加L,float加F。 - 转换顺序:
byte → short → int → long → float → double(char可并入int一路)。 - 运算提升:
byte/short/char运算先升int;boolean不参与转换。
3. 高频坑点清单:
| 坑点 | 表现 | 规避 |
|---|---|---|
| 浮点精度 | 0.1+0.2 != 0.3 |
金额用 BigDecimal |
| 整数除法截断 | 5/2 == 2 |
至少一个操作数转 double |
| 强转截断 | (int)3.99 == 3 |
明确"截断非四舍五入" |
| 整数溢出 | (byte)200 == -56 |
强转前判断范围 |
byte 运算提升 |
byte = byte + byte 报错 |
结果用 int 或强转 |
| 浮点默认 double | float f = 3.14 报错 |
加 F |
一句话总结:变量是容器,类型是容器的规格,转换是容器之间"倒水"——大桶倒小桶(自动)水不外溢,小桶倒大桶(强制)可能洒出来。 理解这三点,Java 的类型体系就立住了。
参考:Java 语言规范(JLS)§4.2(基本类型)、《阿里巴巴 Java 开发手册》、官方教程 The Java™ Tutorials - Primitive Data Types

浙公网安备 33010602011771号