Java 数据类型
Java 是强类型语言,每个变量使用前必须指定类型。Java 的数据类型分两大阵营:基本类型(8 种,小写关键字)和引用类型(类、接口、数组、枚举)。理解它们的区别,是写 Java 代码的根本。
1. 八种基本类型(Primitive Types)
Java 一共 8 种基本类型,分为四类:整型、浮点、字符、布尔。它们直接存值,内存分配在栈上,效率高。
public class BasicTypes {
public static void main(String[] args) {
// 整数类型
byte b = 100; // 1 字节,-128 ~ 127
short s = 1000; // 2 字节
int i = 100000; // 4 字节(最常用)
long big = 10000000000L; // 8 字节,字面量后加 L
// 浮点类型
float f = 3.14f; // 4 字节,字面量后加 F
double d = 3.141592653; // 8 字节(最常用)
// 字符类型
char c = 'A'; // 2 字节,单引号,存 Unicode
// 布尔类型
boolean ok = true; // true 或 false
System.out.println(b + " " + s + " " + i + " " + big);
System.out.println(f + " " + d);
System.out.println(c + " " + ok);
}
}记忆要点:
- 整数字面量默认是
int,声明long必须加L后缀:10000000000L。 - 浮点字面量默认是
double,声明float必须加F后缀:3.14f。 - 浮点数不能精确表示某些小数(如
0.1 + 0.2 ≠ 0.3),涉及金额要用BigDecimal。 boolean只有两个值true/false,不能和整数互转(不像 C/C++)。
2. char 类型详解
char 是单字符类型,用单引号 ',占 2 字节,存的是 Unicode 编码——所以可以放中文、日文、emoji 等任何字符。
public class CharDemo {
public static void main(String[] args) {
char a = 'A'; // 字符
char b = 65; // 65 是 'A' 的 ASCII 码
char c = '中'; // Java char 存 Unicode,可以放中文
char d = '\u4e2d'; // 也可以用 Unicode 转义
System.out.println(a); // A
System.out.println(b); // A(65 自动解释为字符)
System.out.println(c); // 中
System.out.println(d); // 中
// char 本质是整数,可以做加减
System.out.println(a + 1); // 66(char 提升为 int 参与运算)
}
}char 本质是无符号 16 位整数(0~65535),可以直接参与整数运算。但要注意 'a' + 1 的结果是 int 类型(98),不是字符 'b',要再强转回 char:(char)('a' + 1)。
3. 引用类型(Reference Types)
除了 8 种基本类型,其他都是引用类型——包括类(如 String)、接口、数组、枚举。引用类型的变量存的是对象的地址(类似 C 的指针,但不能直接操作地址)。
public class RefTypeDemo {
public static void main(String[] args) {
// 基本类型:直接存值
int a = 10;
int b = a; // b 复制 a 的值
b = 20;
System.out.println(a); // 10(a 不受 b 影响)
// 引用类型:存的是对象的地址
int[] arr1 = {1, 2, 3};
int[] arr2 = arr1; // arr2 复制 arr1 的地址,两者指向同一个数组
arr2[0] = 99;
System.out.println(arr1[0]); // 99(arr1 也变了!)
// 字符串是引用类型,但表现像基本类型(不可变)
String s1 = "hello";
String s2 = s1;
s2 = "world";
System.out.println(s1); // hello(String 不可变,s1 不受影响)
}
}关键区别:基本类型赋值是复制值,引用类型赋值是复制地址(两个变量指向同一对象)。这就是为什么修改 arr2 会影响 arr1——它们其实指向同一个数组。
String 比较特殊:它是引用类型,但不可变(immutable),所以表现有点像基本类型——重新赋值不会改原对象,而是指向新对象。
4. 包装类(Wrapper Classes)
有时候你需要把基本类型当作对象来用——比如放进集合(List<int> 是不允许的!)。Java 为每种基本类型提供了一个包装类(首字母大写),位于 java.lang 包:
import java.util.List;
import java.util.ArrayList;
public class WrapperDemo {
public static void main(String[] args) {
// 基本类型 -> 对应的包装类
// byte -> Byte
// short -> Short
// int -> Integer
// long -> Long
// float -> Float
// double -> Double
// char -> Character
// boolean -> Boolean
// 自动装箱(autoboxing):int -> Integer
Integer i1 = 100; // 等价于 Integer.valueOf(100)
// 自动拆箱(unboxing):Integer -> int
int i2 = i1; // 等价于 i1.intValue()
// 为什么要包装类?
// 集合只能装对象,不能装基本类型
List<Integer> nums = new ArrayList<>();
nums.add(1); // int 自动装箱成 Integer
nums.add(2);
int sum = nums.get(0) + nums.get(1); // Integer 自动拆箱
System.out.println(sum); // 3
}
}自动装箱/拆箱是 Java 5 引入的语法糖,编译器自动插入 valueOf() 和 xxxValue() 调用。但有几个坑:
- Integer 缓存:Integer.valueOf 在 -128~127 范围内会返回缓存对象,所以
Integer a = 100, b = 100; a == b是true,但Integer a = 200, b = 200; a == b是false!比较包装类永远用.equals()。 - 自动拆箱遇 null 会 NPE:
Integer i = null; int n = i;会抛NullPointerException。
5. 类型转换
不同类型之间可以互转,规则:
- 小类型 → 大类型(如 int → long → double)自动转换,不丢精度。
- 大类型 → 小类型(如 double → int)必须强转,可能丢精度或溢出。
public class TypeConvert {
public static void main(String[] args) {
// 1. 自动(隐式)类型转换:小类型 -> 大类型,不丢精度
int i = 100;
long l = i; // int(4字节) -> long(8字节),自动
double d = l; // long -> double,自动
System.out.println(l + " " + d); // 100 100.0
// 2. 强制(显式)类型转换:大类型 -> 小类型,可能丢精度
double pi = 3.99;
int truncated = (int) pi; // 强转成 int,直接截断小数部分
System.out.println(truncated); // 3
long big = 10000000000L;
int small = (int) big; // ⚠️ 超过 int 范围会溢出,结果不对!
System.out.println(small); // 1410065408(溢出后的怪值)
// 3. 字符串与其他类型互转
String s = "123";
int n = Integer.parseInt(s); // 字符串转 int
String str = String.valueOf(n); // int 转字符串
String str2 = n + ""; // 最简单的转字符串技巧
System.out.println(n * 2); // 246
}
}新手要警惕溢出:强转超过目标类型范围时,Java 不会报错,而是会得到一个"怪值"(截断高位字节)。涉及金额、计数的转换要格外小心。
6. 基本类型 vs 包装类,选哪个?
- 能用基本类型就用基本类型:更省内存、更快(没有装箱拆箱开销)。
- 集合元素必须用包装类:如
List<Integer>。 - 数据库/JSON 字段可能为 null:用包装类(Integer 可以是 null,int 不能)。
- 避免无意义的混用:同一字段一会儿 Integer 一会儿 int,容易踩 NPE。
小结
这一章你掌握了 Java 的类型体系:8 种基本类型、引用类型、包装类、类型转换。牢记基本类型存值、引用类型存地址这个本质区别。下一篇我们看 Java 运算符——怎么对这些类型做加减乘除、比较、逻辑运算。
← 上一篇 Java 变量
下一篇 Java 运算符 →