前置知识:第2章——你已经知道变量是什么,能声明变量并赋值
本章分层
- 必读:各基本类型的取值范围与用法、整数溢出、浮点精度陷阱
- 选读:IEEE 754 浮点数表示、类型默认值
- 进阶:Java 基本类型在 JVM 中的内存布局
整数仓库的四个货架
变量村的整数仓库里,老陈师傅指着四个大小不同的货架:
"绝大多数情况下你只用 int。byte 和 short 用在内存紧张的地方(比如嵌入式设备、网络协议解析)。long 只在数字可能超过 20 亿的时候用——long 的字面量末尾要加大写 L。"
// PrimitiveTypes.java
public class PrimitiveTypes {
public static void main(String[] args) {
byte b = 100;
short s = 30000;
int i = 1_000_000; // Java 7 起可以用下划线分隔数字——纯语法糖
long l = 3_000_000_000L; // 超过 int 范围时必须加 L
System.out.println("byte: " + b);
System.out.println("short: " + s);
System.out.println("int: " + i);
System.out.println("long: " + l);
}
}如何运行:
javac PrimitiveTypes.java→java PrimitiveTypes预期输出:byte: 100 short: 30000 int: 1000000 long: 3000000000
overflow——整数溢出的后果
如果往一个 int 里放超范围的数会发生什么?
int max = Integer.MAX_VALUE; // 2147483647
System.out.println(max + 1); // 输出:-2147483648"这不是 bug,这叫整数溢出。"二进制表示已经满了,再加 1 就像汽车的里程表从 999999 翻回 000000——值绕到了负数那一边。long 能存到 9 后面 18 个零,日常用几乎不会溢出。
小数银行的两个柜台
"小数有两种:"
float:4 字节,~7 位有效数字,字面量末尾必须加f或Fdouble:8 字节,~15 位有效数字,字面量加不加d都行
float pi = 3.1415f; // 不加 f 会编译错误——3.1415 默认是 double
double e = 2.71828; // 不加 d 没问题,double 是默认的浮点数的大坑:算不准
double a = 0.1;
double b = 0.2;
System.out.println(a + b); // 你以为输出 0.3实际输出: 0.30000000000000004
"不是 0.3?" 我瞪大眼睛。
"不是。原因和 Java 无关——这是二进制浮点数的固有限制。0.1 在二进制里是一个无限循环小数,跟 1/3 在十进制里是 0.3333... 一样。你用 double 只能存一个近似值,多个近似值加起来误差就冒出来了。"
涉及金钱计算绝对不要用
float或double——后面学BigDecimal时再说。
字符驿站:char 不是字符串
char ch = 'A'; // ✅ char 用单引号包住
char ch2 = "A"; // ❌ 编译错误——双引号是字符串
char ch3 = 'AB'; // ❌ 编译错误——char 只能装一个字符char 是一个 16 位的 Unicode 字符,底层是一个 0~65535 的数字。你可以把 char 当整数用:
char letter = 'A';
System.out.println((int) letter); // 输出:65('A' 的 Unicode 编码)真假哨站:boolean
boolean isReady = true;
boolean isDone = false;只有两个值:true 或 false。在 Java 里,boolean 不能和整数相互转换——不像 C 语言那样把 0 当假、非 0 当真。
常见陷阱
陷阱一:整数除法丢失小数
int a = 5;
int b = 2;
System.out.println(a / b); // 输出:2,不是 2.5两个整数相除,Java 做整数除法——直接舍去小数部分。如果你要小数结果,至少一个操作数要用小数类型:
System.out.println(5 / 2.0); // 输出:2.5
System.out.println(5.0 / 2); // 输出:2.5
System.out.println((double) 5 / 2); // 输出:2.5陷阱二:long 字面量忘加 L
long big = 10000000000; // 编译错误:integer number too large因为 10000000000 被编译器当作 int,但它超出了 int 范围。改正:
long big = 10000000000L; // 加 L 告诉编译器这是 long 字面量陷阱三:float 字面量忘加 f
float f = 3.14; // 编译错误:incompatible types3.14 默认是 double,不能隐式放进 float。改正:
float f = 3.14f;陷阱四:中文标点符号
全角分号 ;、全角引号 "、全角括号 ()——这些在中文文本里看起来正常,但在 Java 代码里都是语法错误。写代码时输入法切到英文模式。
C++ 差异: C++ 的基本类型看起来和 Java 很像,但
int大小不固定——16 位系统上是 2 字节,32/64 位上是 4 字节。Java 的int在任何平台上都是固定的 4 字节,跨平台一致性是 Java 的设计目标之一。Python 差异: Python 没有
byte、short、long的区别——只有一个int,大小只受内存限制。char也不存在——字符就是长度为 1 的字符串。而且 Python 的整数可以任意大,不存在溢出问题。
→ 下一步:类型转换
你认识了每种类型的"房间大小"。但程序里经常需要把数据从一种类型换到另一种类型——int 变成 double,double 变成 int。有些转换安全,有些会丢数据。
第2章续:类型转换