title | shortTitle | isOriginal |
---|---|---|
1.基本数据类型 |
1.基本数据类型 |
true |
本文已收录于:https://github.com/danmuking/all-in-one(持续更新)
- 6 种数字类型:
- 4 种整数型:
byte/8bit
、short/16bit
、int/32bit
、long/64bit
- 2 种浮点型:
float/32bit
、double/64bit
- 4 种整数型:
- 1 种字符类型:
char/16biy
- 1 种布尔型:
boolean/1bit
Java 语言是一个面向对象的语言,讲究一切皆对象,但是 Java 中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了能够形成设计上的统一,Java 为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class),对应关系如下表:
基本类型 | 大小 | 包装器类型 |
---|---|---|
boolean | / | Boolean |
char | 16bit | Character |
byte | 8bit | Byte |
short | 16bit | Short |
int | 32bit | Integer |
long | 64bit | Long |
float | 32bit | Float |
double | 64bit | Double |
void | / | Void |
- 用途:除了定义一些常量和局部变量之外,我们在其他地方比如方法参数、对象属性中很少会使用基本类型来定义变量。并且,包装类型可用于泛型,而基本类型不可以。
- 存储方式:基本数据类型的局部变量存放在 Java 虚拟机栈中的局部变量表中,包装数据类型的成员变量(未被 static 修饰 )存放在 Java 虚拟机的堆中。(包装数据类型本质上是类,遵守类的规则)
- 占用空间:相比于包装类型(对象类型), 基本数据类型占用的空间往往非常小。
- 默认值:成员变量包装类型不赋值就是 null ,而基本类型有默认值且不是 null。
- 比较方式:对于基本数据类型来说,
==
比较的是值。对于包装数据类型来说,==
比较的是对象的内存地址。所有整型包装类对象之间值的比较,全部使用equals()
方法。
在 Java 中,我们经常会这样给包装类型赋值
Integer i = 10;
这就涉及到一个问题,10
是一个基本数据类型,Integer
是一个包装类型,也是一个对象。正常情况下,一个基本数据类型肯定是没有办法给一个对象赋值的。因此,这里 Java 一定进行了一次隐式的类型转换,这个过程就是自动装箱和拆箱。
什么是自动拆装箱?
- 装箱:将基本类型用它们对应的引用类型包装起来;
- 拆箱:将包装类型转换为基本数据类型;
举例:
Integer i = 10; //装箱
int n = i; //拆箱
上面这两行代码对应的字节码为:
L1
LINENUMBER 8 L1
ALOAD 0
BIPUSH 10
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
PUTFIELD AutoBoxTest.i : Ljava/lang/Integer;
L2
LINENUMBER 9 L2
ALOAD 0
ALOAD 0
GETFIELD AutoBoxTest.i : Ljava/lang/Integer;
INVOKEVIRTUAL java/lang/Integer.intValue ()I
PUTFIELD AutoBoxTest.n : I
RETURN
从字节码中,我们发现装箱其实就是调用了 包装类的valueOf()
方法,拆箱其实就是调用了xxxValue()
方法。
因此,
Integer i = 10
等价于Integer i = Integer.valueOf(10)
int n = i
等价于int n = i.intValue();
如果频繁拆装箱的话,也会严重影响系统的性能。我们应该尽量避免不必要的拆装箱操作。
Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能。
Byte
,Short
,Integer
,Long
这 4 种包装类默认创建了数值 [-128,127]
的相应类型的缓存数据,Character
创建了数值在 [0,127]
范围的缓存数据,Boolean
直接返回True
or False
。
只有基于
valueOf()
实现的方法能够利用到缓存机制,如果直接创建一个对象,例如new Integer(1)
将会创建一个新的对象,没有办法利用缓存来提升性能。
转换自动类型转换(自动类型提升)是 Java 编译器在不需要显式转换的情况下,将一种基本数据类型自动转换为另一种基本数据类型的过程。这种转换通常发生在表达式求值期间,当不同类型的数据需要相互兼容时。自动类型转换遵循以下规则:
- 如果任一操作数是 double 类型,其他操作数将被转换为 double 类型。
- 否则,如果任一操作数是 float 类型,其他操作数将被转换为 float 类型。
- 否则,如果任一操作数是 long 类型,其他操作数将被转换为 long 类型。
- 否则,所有操作数将被转换为 int 类型。
需要注意的是,自动类型转换只发生在兼容类型之间。例如,从较小的数据类型(如 int)到较大的数据类型(如 long 或 double)的转换是安全的,因为较大的数据类型可以容纳较小数据类型的所有可能值。
规则如下:
byte -> short -> int -> long -> float -> double
char -> int -> long -> float -> double
强制类型转换是 Java 中将一种数据类型显式转换为另一种数据类型的过程。与自动类型转换不同,强制类型转换需要程序员显式地指定要执行的转换。强制类型转换在以下情况中可能需要:
- 将较大的数据类型转换为较小的数据类型。
- 将浮点数转换为整数。
- 将字符类型转换为数值类型。
需要注意的是,强制类型转换可能会导致数据丢失或精度降低,因为目标类型可能无法容纳原始类型的所有可能值。因此,在进行强制类型转换时,需要确保转换后的值仍然在目标类型的范围内。
下面是一个简单的例子:
double doubleValue = 42.8;
// 强制类型转换:将 double 类型转换为 int 类型
int intValue = (int) doubleValue;
System.out.println("整数值: " + intValue); // 输出:整数值: 42
这段代码将一个double
类型的变量doubleValue
值强行赋给为int
类型的变量intValue
,在这个过程中,由于int
类型无法表示小数部分,因此小数部分将被截断。
虽然这部分知识点在面试中很少出现,但是一旦答不上来,面试官很容易就给你打上一个基础不扎实的标签。所幸这部分知识点其实也不多,所以还是尽量花点时间看一看。