1 缘起
补充字节码相关知识时,发现基础数据类型、包装类型和引用类型在字节码层面的差异,
未接触字节码前,只是理论上直到数据存储方式不同,
没有证明材料,通过反编译字节码,发现,不同的数据大类型,分配空间是不同的,
分享如下,帮助读者进一步了解基础数据类型、包装类型和引用类型的差别。
2 数据类型
2.1 基础数据类型
基础数据类型存储在栈中,直接申请内存。
Java提供8中基础数据类型,int、long、float、double、boolean、char、byte和short。
2.2 包装类型
包装类型:基础数据类型对应的类。
在栈中存储引用,堆中存储数据。
与基础数据类型一一对应,因此,也有8中包装类型,对应关系:
包装类型,既然是包装,则有装和拆的概念,这里是装箱和拆箱。
- 装箱:将数据存储为对象,如Integer.valueOf()T;
- 拆箱:将对象转为基础类型,如var1.intValue();
2.3 引用类型
引用类型有三种:类、接口和数组,
栈中存储引用,堆中存储实际内容。
3 Code实践
源码默认情况下会折叠,为方便查看,
先给出源码对应的字节码关系结果,
后面会给出完整的源码。
字节码解析:https://blog.csdn.net/Xin_101/article/details/126288966
3.1 基础类型
基础类型及字节码对应关系如下图所示。
怎么证明是基础数据类型?
字节码关系如下图所示:
3.2 包装类型
基础数据类型对应的包装类类型及对应的字节码关系如下图所示。
证明包装类型为引用类型存储。
3.3 引用类型
引用类型及对应的字节码如下图所示。
源码
package com.monkey.java_study.clzz;
import com.monkey.java_study.common.entity.UserEntity;
import com.monkey.java_study.proxy.jdk_proxy.IUserService;
import com.monkey.java_study.proxy.jdk_proxy.impl.UserServiceImpl;
/**
* 数据类型字节码测试.
*
* @author xindaqi
* @since 2022-08-12 15:26
*/
public class DataTypeByteCodeTest {
public void basicType() {
// iconst_1
// istore_1
int var1 = 1;
// lconst_1
// lstore_2
long var2 = 1L;
// fconst_1
// fstore
float var3 = 1.0f;
// dconst_1
// dstore
double var4 = 1.0;
// iconst_1
// istore
boolean var5 = true;
// bipush
// istore
char var6 = 'a';
// bipush
// istore
byte var7 = 0x10;
// iconst_1
// istore
short var8 = 1;
}
public void packageType() {
// iconst_1
// invokestatic:自动装箱
// astore_1
Integer var1 = 1;
// lconst_1
// invokestatic:自动装箱
// astore_2
Long var2 = 1L;
// fconst_1
// invokestatic:自动装箱
// astore_3
Float var3 = 1.0f;
// dconst_1
// invokestatic:自动装箱
// astore
Double var4 = 1.0;
// iconst_1
// invokestatic:自动装箱
// astore
Boolean var5 = true;
// bipush
// invokestatic:自动装箱
// astore
Character var6 = 'a';
// iconst_1
// invokestatic:自动装箱
// astore
Byte var7 = 0x01;
// iconst_1
// invokestatic:自动装箱
// astore
Short var8 = 1;
}
public void referenceType() {
// new
// dup
// invokespecial
// astore_1
UserEntity userEntity = new UserEntity();
// new
// dup
// invokespecial
// astore_2
IUserService userService = new UserServiceImpl();
// iconst_2
// newarray
// dup
// iconst_0
// iconst_0
// iastore
// dup
// iconst_1
int[] var1 = {0, 1};
}
public static void main(String[] args) {
}
}
4 反编译
4.1 基础数据类型
源码与字节码映射关系如下图所示。
4.2 包装类型
源码与字节码映射关系如下图所示。
4.3 引用类型
源码与字节码映射关系如下图所示。
完整结果
PS D:\java-basic-with-maven\target\classes\com\monkey\java_study\clzz> javap -c .\DataTypeByteCodeTest.class
Compiled from "DataTypeByteCodeTest.java"
public class com.monkey.java_study.clzz.DataTypeByteCodeTest {
public com.monkey.java_study.clzz.DataTypeByteCodeTest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public void basicType();
Code:
0: iconst_1
1: istore_1
2: lconst_1
3: lstore_2
4: fconst_1
5: fstore 4
7: dconst_1
8: dstore 5
10: iconst_1
11: istore 7
13: bipush 97
15: istore 8
17: bipush 16
19: istore 9
21: iconst_1
22: istore 10
24: return
public void packageType();
Code:
0: iconst_1
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_1
5: lconst_1
6: invokestatic #3 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
9: astore_2
10: fconst_1
11: invokestatic #4 // Method java/lang/Float.valueOf:(F)Ljava/lang/Float;
14: astore_3
15: dconst_1
16: invokestatic #5 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
19: astore 4
21: iconst_1
22: invokestatic #6 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
25: astore 5
27: bipush 97
29: invokestatic #7 // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
32: astore 6
34: iconst_1
35: invokestatic #8 // Method java/lang/Byte.valueOf:(B)Ljava/lang/Byte;
38: astore 7
40: iconst_1
41: invokestatic #9 // Method java/lang/Short.valueOf:(S)Ljava/lang/Short;
Code:
0: return
}
5 小结
(1)基础数据类型存储在栈中,直接申请内存,Java提供8中基础数据类型,int、long、float、double、boolean、char、byte和short;
(2)包装类型:基础数据类型对应的类。在栈中存储引用,堆中存储数据;
(3)装箱:将数据存储为对象,如Integer.valueOf()T;拆箱:将对象转为基础类型,如var1.intValue();
(4)引用类型有三种:类、接口和数组,栈中存储引用,堆中存储实际内容。