java中的基本数据类型与JVM中的基本数据类型

举报
云上有未来 发表于 2020/04/18 16:27:17 2020/04/18
【摘要】 java是一门面向对象的语言,但是对于“基本数据类型”是特殊的。之所以java中引入基本数据类型,是因为通过执行效率以及内存使用来提高应用软件的性能。

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

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。