Java 中的数据类型决定了变量可以保存什么数据,以及这些数据在内存中如何表示。学习数据类型时,可以先从"字面量"和"变量"开始。
1. 字面量
字面量是直接写在 Java 源代码中的固定值。例如:
"hello"
123
3.14
'A'
true
null
常见的字面量有以下几类。
字符串字面量
由双引号括起来:
"12345"
"hello"
"你好"
字符串不是基本数据类型,而是 String 类的对象。
整数字面量
不带小数点的数字:
100
-20
0
整数字面量默认是 int 类型。如果要表示 long,通常在数字后加 L:
long a = 100L;
Java 还支持二进制、八进制和十六进制写法:
int a = 0b1010; // 二进制
int b = 012; // 八进制
int c = 0xFF; // 十六进制
浮点数字面量
带小数点的数字:
3.14
0.49
-2.5
浮点数字面量默认是 double 类型。如果要表示 float,需要加 F 或 f:
float f = 3.14F;
double d = 3.14;
字符字面量
由单引号括起来,只能表示一个字符:
'A'
'1'
'乐'
字符串使用双引号,字符使用单引号:
String s = "A";
char c = 'A';
布尔字面量
布尔类型只有两个值:
true
false
Java 不会把 0 和 1 自动转换成 false 和 true。
null 字面量
null 表示没有引用任何对象,只能赋给引用类型变量:
String name = null;
它不能赋给基本数据类型:
// int number = null; // 编译错误
2. 数据类型
Java 的数据类型分为基本数据类型和引用数据类型。
2.1 基本数据类型
Java 有 8 种基本数据类型:
| 类型 | 占用空间 | 说明 |
|---|---|---|
byte |
1 字节 | -128 到 127 |
short |
2 字节 | -32768 到 32767 |
int |
4 字节 | 常用整数类型 |
long |
8 字节 | 长整数 |
float |
4 字节 | 单精度浮点数 |
double |
8 字节 | 双精度浮点数 |
char |
2 字节 | UTF-16 代码单元 |
boolean |
规范未规定具体大小 | true 或 false |
这些大小由 Java 语言规范规定,与操作系统是 16 位、32 位还是 64 位无关。
整数类型的默认类型是 int,浮点数字面量的默认类型是 double。
2.2 引用数据类型
引用类型包括类、接口、数组、枚举等。
String name = "Tom";
int[] numbers = new int[3];
引用类型变量保存的是对象的引用。引用类型变量可以保存 null。
常见的基本类型包装类如下:
| 基本类型 | 包装类 |
|---|---|
byte |
Byte |
short |
Short |
int |
Integer |
long |
Long |
float |
Float |
double |
Double |
char |
Character |
boolean |
Boolean |
3. 变量
变量是程序中用来保存数据的名称。一个变量通常包含三部分:
int age = 18;
这里:
int是变量类型;age是变量名;18是初始值。
3.1 变量的声明和初始化
可以在声明变量时直接赋值:
int a = 10;
System.out.println(a);
也可以先声明,再赋值:
int b;
b = 10;
System.out.println(b);
局部变量在使用前必须完成赋值:
int c;
// System.out.println(c); // 编译错误
c = 100;
System.out.println(c);
成员变量会自动获得默认值:
class User {
int age; // 0
boolean active; // false
String name; // null
}
通常建议在声明局部变量时直接给出有意义的初始值。
4. 整数类型
4.1 int
int 占 4 个字节,范围是:
-2147483648 到 2147483647
可以使用包装类 Integer 查看范围:
System.out.println(Integer.MIN_VALUE);
System.out.println(Integer.MAX_VALUE);
下面的代码会编译失败:
// int number = 12345678901234;
因为这个整数字面量超出了 int 的范围。这个数仍在 long 范围内,可以写成:
long number = 12345678901234L;
4.2 long
long 占 8 个字节,范围是:
-2^63 到 2^63 - 1
定义 long 字面量时,建议加大写字母 L:
long count = 100L;
小写 l 也可以,但容易和数字 1 混淆。
4.3 short
short 占 2 个字节,范围是:
-32768 到 32767
它的包装类是 Short。
4.4 byte
byte 占 1 个字节,范围是:
-128 到 127
它的包装类是 Byte。
Java 中有多种整数类型,主要是为了根据数据范围和存储需求选择合适的类型。日常开发中,整数通常优先使用 int。
5. 浮点类型
float 占 4 个字节,double 占 8 个字节。double 的精度通常更高,也是 Java 中更常用的浮点类型。
double price = 3.14;
float rate = 0.5F;
浮点数按照 IEEE 754 标准存储。很多十进制小数无法用二进制精确表示,因此浮点计算可能出现细小误差:
double result = 0.1 + 0.2;
System.out.println(result); // 可能输出 0.30000000000000004
所以,float 和 double 适合表示近似值。涉及金额等需要精确计算的场景,可以使用 BigDecimal。
6. 字符类型
char 占 2 个字节,保存一个 UTF-16 代码单元:
public class Main {
public static void main(String[] args) {
char ch1 = 'a';
char ch2 = 97;
char ch3 = '乐';
System.out.println(ch1); // a
System.out.println(ch2); // a
System.out.println(ch3); // 乐
}
}
许多常见汉字可以用一个 char 表示,但并不是所有 Unicode 字符都只占一个 char。例如,一些 emoji 需要两个 UTF-16 代码单元。
7. 布尔类型
boolean 只有两个值:
public class Main {
public static void main(String[] args) {
boolean b1 = true;
boolean b2 = false;
System.out.println(b1);
System.out.println(b2);
}
}
下面的写法是错误的:
// boolean b3 = 1;
Java 不支持整数和布尔值之间的自动转换。
8. 类型转换
当不同类型的数据一起使用时,Java 可能进行自动类型转换,也可能要求手动强制转换。
8.1 自动类型转换
通常,表示范围较小的类型可以自动转换为表示范围较大的类型:
int a = 10;
long b = a;
这里 int 自动转换成了 long。
float f = 10;
double d = f;
8.2 强制类型转换
把范围较大的类型赋给范围较小的类型时,需要强制转换:
long a = 20L;
int b = (int) a;
强制转换可能造成数据截断、溢出或精度丢失:
long value = 3000000000L;
int result = (int) value;
即使转换语法正确,结果也不一定符合原来的数值。
字面量在赋值时会进行范围检查:
byte a = 10; // 可以
// byte b = 128; // 编译错误
不同类型之间也不是都能转换。例如,int 和 String 不能直接通过强制类型转换互相转换,需要使用专门的方法。
9. 类型提升
byte、short 和 char 参与算术运算时,通常会先提升为 int:
byte a = 10;
byte b = 20;
// byte result = a + b; // 编译错误
int result = a + b;
如果确实需要得到 byte,可以手动转换:
byte result = (byte) (a + b);
不同类型一起运算时,较小的类型通常会提升为较大的类型:
int a = 10;
long b = 20L;
long result = a + b;
10. 字符串
Java 没有内置的字符串基本数据类型,字符串由 String 类表示:
String str1 = "Hello";
String str2 = "World";
String result = str1 + " " + str2;
System.out.println(result); // Hello World
字符串和其他类型使用 + 运算时,会进行字符串拼接:
int a = 10;
int b = 20;
System.out.println("a = " + a + ", b = " + b);
System.out.println("a + b = " + a + b);
System.out.println("a + b = " + (a + b));
System.out.println(a + b);
输出结果:
a = 10, b = 20
a + b = 1020
a + b = 30
30
+ 会从左到右计算。一旦表达式中出现字符串,后面的内容通常都会变成字符串拼接。
11. int 转换为 String
可以使用字符串拼接:
int num = 10;
String str1 = num + "";
更推荐使用 String.valueOf:
int num = 10;
String str = String.valueOf(num);
System.out.println(str);
12. String 转换为 int
可以使用 Integer.parseInt:
public class Main {
public static void main(String[] args) {
String str = "1024";
int num = Integer.parseInt(str);
System.out.println(num);
}
}
如果字符串不是合法的整数,会抛出 NumberFormatException:
// Integer.parseInt("abc");
// Integer.parseInt("1.2");
因此,处理用户输入时,需要考虑输入内容是否符合整数格式。