钩子:1500 塞进 byte,变成了负数
先看一段代码:
int i = 1500;
byte j = (byte) i;
System.out.println(j);
输出是 -36。

1500 好好的,塞进 byte 就成了负数。没有报错,没有警告,程序照常跑,数据已经错了。
这是 Java 类型转换的第一个坑。这一篇我们把 8 种基本类型和转换规则一次讲清楚,顺便把新手最容易踩的坑提前排掉。
01 Java 数据类型的分类
Java 的数据类型分两大类:基本数据类型和引用数据类型。
基本类型一共 8 种,先看这张表,建议收藏:
| 分类 | 类型 | 字节 | 取值范围 |
|---|---|---|---|
| 整数 | byte | 1 | -128 ~ 127 |
| 整数 | short | 2 | -32,768 ~ 32,767 |
| 整数 | int | 4 | 约 ±21 亿 |
| 整数 | long | 8 | 约 ±9.2 × 10^18 |
| 浮点 | float | 4 | 约 ±3.4 × 10^38(7 位有效数字) |
| 浮点 | double | 8 | 约 ±1.8 × 10^308(15 位有效数字) |
| 字符 | char | 2 | Unicode 所有字符 |
| 布尔 | boolean | - | true / false |
几个新手常问的点:
- int 是 Java 里整数的默认类型,你直接写 100,它就是 int。
- double 是小数的默认类型。float 赋值要加 f:
float f = 1.5f,不加直接编译报错。 - boolean 只有 true 和 false,它和数字之间没有转换关系,这点和 C 语言不一样。
- long 赋值建议加大写 L:
long t = 100000000000L。小写 l 的话,1l看起来太像 11,别问我是怎么知道的。
02 自动类型转换,小转大随便转
容量小的类型可以自动转成容量大的类型,编译器不拦你:

byte → short → int → long → float → double
char 也能自动转成 int,比如字符 a 参与运算时会自动变成 97。
方向记住就行:小的往大的流。
有人会问,long 是 8 个字节,float 才 4 个字节,为什么 long 能自动转 float?因为 float 的存储方式是"有效数字 + 指数",能表示的范围比 long 大得多,只是精度不如 long。所以 long 转 float 也会丢精度,记住这个伏笔。
03 强制类型转换,坑全在这一节
反方向转就要强制转换,语法是把目标类型写在括号里。
坑 1:溢出,数据悄悄变错
就是开头那段代码:
int i = 1500;
byte j = (byte) i;
System.out.println(j); // -36
byte 只保留 int 的最低 8 位。1500 的二进制低 8 位是 220,按有符号数解释就是 -36。
数据没有丢在明面上,它直接错了。数据库 id、金额、时间戳,这些字段一旦溢出都是线上事故。所以选类型之前先想清楚数据的量级。
坑 2:精度,小数说没就没
double d = 99.5;
int m = (int) d;
System.out.println(m); // 99
强制转 int 不四舍五入,直接砍掉小数部分。想要四舍五入,用 Math.round(d)。
坑 3:编译器比你想象中严格
byte b = 10;
b = b + 1; // 编译报错
右边 b + 1 的结果是 int 类型,往 byte 里塞需要强制转换,编译器直接报 incompatible types。新手经常在这卡半小时。写全就是这样:b = (byte)(b + 1),不过实际开发里建议直接用 int。
04 引用类型的转换,先知道有这么回事
这块后面讲面向对象时还会细说,现在先记两句:
- 子类转父类(向上转型)是自动的,Dog 当 Animal 用没问题。
- 父类转子类(向下转型)要强转,转之前用 instanceof 检查,不然运行时会抛 ClassCastException。
Animal a = new Dog();
Dog d = (Dog) a; // 没问题,a 本来就是 Dog
Animal a2 = new Cat();
Dog d2 = (Dog) a2; // 编译能过,运行直接抛异常
05 和 String 互转,天天都在用
int 转 String:
String s1 = String.valueOf(i);
String s2 = "" + i; // 偷懒写法,面试可以说说原理
String 转 int:
int i1 = Integer.parseInt(s);
注意 parseInt 遇到 "abc" 这种会抛 NumberFormatException,解析用户输入前记得 try 一下。
基本类型和包装类(Integer、Double 这些)的互转就是自动装箱拆箱,留到讲集合的时候细说。现在记住两个方向就行:Integer.valueOf(a) 把 int 变 Integer,a.intValue() 把 Integer 变回 int。
本文示例代码均已本地实测通过,可直接运行。
系列下一篇:《运算符与 i++ 的坑》——有个坑和今天的三号坑是亲戚,先剧透一句:++i 和 i++ 在面试里出现频率极高。
橙码酱,分享更有用的技术知识,助你成为更优秀的开发者。