java中的基本数据类型与JVM中的基本数据类型
java是一门面向对象的语言,但是对于“基本数据类型”是特殊的。之所以java中引入基本数据类型,是因为通过执行效率以及内存使用来提高应用软件的性能。
//正常情况下
public class Foo {
public static void main (String [] args){
boolean flag = true;
if(flag){
System.out.println("HELLO,JAVA!");
}
if(flag==true){
System.out.println("HELLO,JVM!");
}
}
}
//异常情况
public class Foo {
public static void main (String [] args){
boolean flag = 2;//java编译无法通过
if(flag){
System.out.println("HELLO,JAVA!");
}
if(flag==true){
System.out.println("HELLO,JVM!");
}
}
}
对于java语言本身来说,第一种情况是合法。因为java编译器定义的boolean类型只包括“true”“false”两种;
对于java虚拟机来说,两种情况都是合法的。因为编译器将boolean类型映射为整数类型,虚拟机都是可以识别的。只不过java编译器特殊化处理,将“true”映射为“1”,“false”映射为“0”(这也就是为什么java虚拟机定义得更加广泛)。
将上述两种情况下的java分别反编译为字节码,如下图:
//第一种情况
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: iconst_1
1: istore_1
2: iload_1
3: ifeq 14
6: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
9: ldc #3 // String HELLO,JAVA!
11: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
14: iload_1
15: iconst_1
16: if_icmpne 27
19: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
22: ldc #5 // String HELLO,JVM!
24: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
27: return
LineNumberTable:
line 4: 0
line 5: 2
line 6: 6
line 8: 14
line 9: 19
line 11: 27
LocalVariableTable:
Start Length Slot Name Signature
0 28 0 args [Ljava/lang/String;
2 26 1 flag Z
StackMapTable: number_of_entries = 2
frame_type = 252 /* append */
offset_delta = 14
locals = [ int ]
frame_type = 12 /* same */
执行结果:不用多说,大家都知道。
//第二种情况
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: iconst_2
1: istore_1
2: iload_1
3: ifeq 14
6: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
9: ldc #1 // String HELLO,JAVA!
11: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
14: iload_1
15: iconst_1
16: if_icmpne 27
19: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
22: ldc #2 // String HELLO,JVM!
24: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
27: return
StackMapTable: number_of_entries = 2
frame_type = 252 /* append */
offset_delta = 14
locals = [ int ]
frame_type = 12 /* same */
执行结果:只有 HELLO,JAVA!
从以上结果的不同,我们可以看出:
两个if语句的字节码指令有所不同-----ifeq与if_icmpne
ifeq代表:只要传入的参数不为"0",则继续执行,否则跳转;
if_icmpne代表:只有传入的参数为"1",才继续执行,否则跳转。
上述改变字节码可以通过asmtools工具来实现。
对于java基本数据类型的范围,如下图所示:
从前面的boolean类型,我们可以看出,在java虚拟中,boolean类型可以定义为“0”“1”之外的整数类型,同样的,对于其他基本数据类型,也可以定义超出范围的数值。不过,在正常使用java编译器的话,这种情况是不会出现的。
除了基本数据类型的范围之外,还需要知道基本数据类型的大小。
在栈中,在32位hotspot虚拟机中,对于32位数据类型以内的数据类型:boolean/byte/short/char/reference/float/int占用4个字节,相当于1个slot,如果是64位数据类型:double/long的话,则占用2个slot;在64位hotspot虚拟机中,boolean/byte/short/char占用8个字节。
在堆中,基本数据类型boolean/byte/short/char分别占用1/1/2/2个字节。
存储:如果int类型的数值以这四种基本数据存储的话,则会进行掩码操作,因为这四种类型的长度不足以容纳int类型(8)。boolean类型比较特殊,因为boolean直接以byte存储的,但是又为了保证boolean在堆上的值是合法的,所以只取了最后一位来作为值进行存储。
加载:如果这四种基本数据类型加载到栈中的话,则在高位进行填充。
————————————————
版权声明:本文为CSDN博主「y5946622」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/y5946622/java/article/details/81207605
- 点赞
- 收藏
- 关注作者
评论(0)