目录
在Java中,数据类型主要分为两大类:基本数据类型和引用数据类型。本文主要介绍基本数据类型、类型转换以及类型提升。
一、基本数据类型
基本数据类型又分为四大类,分别是整数类型、浮点类型、字符类型、布尔类型。
数据类型 | 关键字 | 内存占用 | 范围 |
---|---|---|---|
字节型 | byte | 1字节 | -128 到 127 |
短整形 | short | 2字节 | -32,768 到 32,767 |
整形 | int | 4字节 | -2^31 到 2^31-1 |
长整形 | long | 8字节 | -2^63 到 2^63-1 |
单精度浮点数
| float | 4字节 | 约 ±3.40282347E+38F (6-7 位小数) |
双精度浮点数 | double | 8字节 | 约 ±1.79769313486231570E+308 (15 位小数) |
字符型 | char | 2字节 | 0 到 65,535 |
布尔型
| boolean | 不定 | 依赖JVM 实现,通常为1位或1字节,两种取值:true或false |
byte b = 10; //字节型变量
short s = 100; //短整型变量
int i = 1000; //整形变量
long l = 10000L; //长整形变量
float f = 1.0f; //单精度浮点型变量
double d = 3.14; //双精度浮点型变量
char c = 'a'; //字符型变量
boolean flag = false;//布尔型变量
1.在Java 中,基本数据类型的内存大小是固定的,并不会因为系统或平台的变化而改变。这是因为 Java 虚拟机(JVM)规范定义了这些类型的大小,以确保 Java 程序具有可移植性和一致的行为。所以不论是在16位系统还是32位系统,int都占用4个字节,long都占8个字节
2.整形和浮点型都是带有符号的
3.在Java中整型默认为int型,浮点型默认为double
4.因为整形默认为int,为了区分int和long类型,可以在数字后面加上L或l,为了区分数字1,推荐加大写的'L'。
5.因为浮点型默认为double,所以在浮点型的字面值必须加上f或F结尾,否则编译器会将其视为double类型的字面值。由于double类型具有更高的精度,不能直接赋值给float类型而不进行显式转换,float = 1.0会报错。
6.Java 的 boolean 类型和 int 不能相互转换,不存在 非零 表示 true, 0 表示 false 这样的用法
二、类型转换
2.1 自动类型转换(隐式类型转换)
隐式类型转换是指在不需要显式声明的情况下,Java编译器自动完成的数据类型转换。通常,较小范围或精度的类型自动转换为较大范围或精度的类型,以防止数据丢失。
示例1:
- 从较小范围或精度的类型到较大范围或精度的类型(如int到long,float到double,int到double)。
public static void main(String[] args) { int a = 100; long b = 10L; b = a; //a和b都是整形,a的范围小,b的范围大, //当将a赋值给b时,编译器会自动将a提升为long类型,然后赋值 a = b; //编译报错,long的范围比int范围大,会有数据丢失,不安全 float f = 3.14f; double d = 2.14; d = f; //编译器会将f转换为double,然后进行赋值 f = d; //编译报错,double表示数据范围大, // 直接将float交给double会有数据丢失,不安全 int i = 10; double j = 3.14; j = i; //编译器会将i转换为double,然后进行赋值 i = j; //编译报错,double表示数据范围大, // 直接将double交给int会有数据丢失,不安全。 }
示例2:
- 当常量值在目标类型范围内时,可以进行从int到byte、short的转换。
public static void main(String[] args) { byte b = 10; short s = 100; // 上面两个过程涉及类型转换。在java中整数的默认类型是int // 这里的10是一个整数常量,它的默认类型是 int。 // 但是,由于10是一个可以表示为byte类型的值(即它在byte类型的范围内,-128 到 127), // 因此编译器会自动将这个 int 类型的常量转换为byte类型。 float f = 3.14; // 在 Java 中,浮点数的默认类型是 double, // 所以 3.14 被解释为一个 double 类型的字面量。 // 尽管 3.14 在 float 类型的范围内, // 但 Java 并不会自动将 double 转换为 float, // 因为这是一种隐式类型转换,可能会导致精度损失。 // 因此,Java 需要显式的类型转换来表明开发者清楚地了解这种转换可能带来的影响。 byte r = 128; 编译失败,257超过了byte的数据范围,有数据丢失 }
2.2 强制类型转换(显式类型转换)
显式类型转换是指通过强制转换运算符将一种数据类型转换为另一种数据类型。通常在较大范围或精度的类型转换为较小范围或精度的类型时使用,以避免编译错误和数据丢失。
示例:
public static void main(String[] args) {
int a = 10;
long b = 100L;
b = a; // int-->long,数据范围由小到大,隐式转换
a = (int)b; // long-->int, 数据范围由大到小,需要强转,否则编译失败
float f = 3.14F;
double d = 5.12;
d = f; // float-->double,数据范围由小到大,隐式转换
f = (float)d; // double-->float, 数据范围由大到小,需要强转,否则编译失败
a = d; // 报错,类型不兼容
a = (int)d; // int没有double表示的数据范围大,需要强转,小数点之后全部丢弃
byte b1 = 100; // 100默认为int,没有超过byte范围,隐式转换
byte b2 = (byte)257; // 257默认为int,超过byte范围,需要显示转换,否则报错
boolean flag = true;
a = flag; // 编译失败:类型不兼容
flag = a; // 编译失败:类型不兼容
}
1. 不同数字类型的变量之间赋值 , 表示范围更小的类型能隐式转换成范围较大的类型2. 如果需要把范围大的类型赋值给范围小的 , 需要强制类型转换 , 但是 可能精度丢失3. 将一个字面值常量进行赋值的时候 , Java 会自动针对数字范围进行检查4. 强制类型转换不一定能成功,不相干的类型不能互相转换
三、类型提升
在 Java 中,类型提升是指在表达式中不同类型的操作数被自动转换为同一类型以执行操作的过程。这通常发生在算术运算和赋值运算中,以确保数据类型的兼容性和避免潜在的数据丢失。
3.1 算术运算中的类型提升
3.1.1 整型提升
先看一段代码:
这段代码会报错,是因为在Java 中,当两个byte类型的变量进行算术运算时,它们会被自动提升为int类型。然后,运算的结果也是int类型。由于不能直接将int类型赋值给byte类型(因为int的范围比int大),因此会产生编译错误。
当byte、short和char类型的变量参与运算时,它们首先会被提升为int
3.1.2 浮点数提升
- 如果一个操作数是double类型,另一个操作数将被提升为double。
- 如果没有double类型的操作数,但是有一个float类型的操作数,另一个操作数将被提升为float。
public static void main(String[] args) {
double b= 10;
int a = 4;
double c = a+b; //a发生类型提升,由int类型提升为double 类型,以便进行浮点数运算。
System.out.println(c);
float f = 3.14F;
float d = a+f; //类型提升:a 从 int 提升为 float
System.out.println(d);
double x = b + f; //类型提升:f 从float 提升为 double
}
3.2 赋值中的类型提升
赋值操作中也会涉及类型提升,但通常是由隐式类型转换实现的。Java 赋值时的类型转换规则是:
- 可以从低精度类型提升到高精度类型。例如,从int到long,float到double。
- 不能从高精度类型赋值到低精度类型,除非使用显式类型转换(强制转换)
3.3 类型提升的规则
byte
->short
->int
->long
->float
->double
char
->int
->long
->float
->double
总而言之,在类型转换与类型提升中,低精度类型提升到高精度类型与低范围类型提升到高范围类型是相对容易的,编译器可能就会自动转化(隐式),而高精度类型转化到低精度类型与高范围类型转换到低范围类型是不容易的,需要强制类型转换(显示类型转换)。但是这都可能造成数据丢失,所以需要慎重考虑对类型的转换。
四、 引用类型
基本数据创建的变量,称为基本变量,该变量空间中直接存放的是其对应的值;引用数据类型用于存储对象的地址(或引用),而不是对象本身,引用数据类型创建的变量,一般称为对象的引用,其空间中存储的是对象所在空间的地址。