Java 的基本类型

Java 包括了八种基本类型,明细如下:

Java 的基本类型都有对应的值域和默认值。byte,short,int,long,float以及double的值域依次扩大,前面的值域都被后面的值域包括在内。所以,从前面的基本类型转换成后面的基本类型,无需强制转换。补充:尽管它们的默认值表示不一样,但是在内存中都是 0.

boolean 和 char 是唯二的无符号类型。boolean 的取值范围是 0 或者 1,char 类型的取值范围是 [0,65535]。通常可以认定 char 类型的值为非负数,这种特性十分有用,比如说作为数组的索引等。

局部变量也可以存储超出它们取值范围的数值,但是这些超出取值范围的数字会带来一些麻烦。例如: char 类型的局部变量实际上有可能是负数。但是在正常使用 Java 编译器的情况下,生成的字节码会遵守 Java 虚拟机规范对编译器的约束,因此无需过分短信局部变量会超出他们的取值范围。

浮点类型中的 float,通常有两个 0,+0.0F 和 -0.0F。这两个 0 的表示,在内存中的数值是不同的,但是在 Java 中 +0.0F == -0.0F 会返回真。有了这两者,我们就可以定义浮点数中的正无穷和负无穷。

任意正浮点数 (不包括 +0.0F) 除以 +0.0F 得到的值就是正无穷,内存中的值为 0x7F800000

任意负浮点数 (不包括 -0.0F) 除以 -0.0F 得到的值就是负无穷,内存中的值为 0xFF800000

[0x7F800001,0x7FFFFFFF] 和 [0xFF800001,0xFFFFFFFF] 对应的数值都是 NaN。一般我们计算得出的 NaN,比如说通过 +0.0F/-0.0F 得出的内存值为 0x7FC00000,这个数值我们称之为标准的 NaN,其他的统称为不标准的 NaN。

NaN 有一个特性:除了 "!=" 始终返回 true 以为,所有其他的比较结果都会返回 false。例如: "NaN < 1.0F" ,"NaN > 1.0F" 返回 false。对于任意浮点数 f ,无论它是 0 还是 NaN,"f != NaN" 始终返回 true。

Java 基本类型的大小

Java 虚拟机每调用一个 Java 方法的时候,都会创建一个栈帧。为了方便理解,只讨论供解释器使用的解释栈帧。

这种栈帧包含两个部分:局部变量区和字节码的操作数栈。这里的局部变量指的是广义的,包含普通意义下的局部变量,还包含实例方法中的 "this指针" 以及方法接受到的参数。

  • 下面总结基本类型的存储。

在 Java 虚拟机规范中,局部变量区等价于一个数组,并且可以用正整数来索引。除了 long 和 double 的值需要两个数组单元来存储之外,其他的基本类型以及引用类型的值均占用一个数组单元。也就是说,boolean,byte,chart,short 这四种类型在栈上占用的空间和 int 是一样的,和引用类型也是一样的。因此,在 32 位的 HotSpot 中,这些类型在栈上将占用 4 个字节,而在 64 位的 HotSpot 中,他们将占 8 个字节。

上述情况进存在于局部变量,并不会出现在存储于堆中的字段或者数组元素上。对于 byte,chart,short 这三种类型的字段或者数组单元,它们在堆上占用的空间分别是 1 字节,2 字节,2 字节,跟它们的值域是相吻合的。

将一个 int 类型的值存储到这些类型的字段或者数组时,相当于做了一次隐式的掩码操作。举例: int 类型的值存入声明为 char 类型的字段里时,由于该字段仅占两字节,所以高位字节便会被截取。

boolean 字段和 boolean 数组比较特殊。在 HotSpot 中,boolean 字段占用一字节,而 boolean 数组则直接用 byte 数组来实现。为了保证堆中 boolean

值的合法性, HotSpot 在存储时显示地进行掩码操作,也就说说只取低位 (最后一位) 的值存入 boolean 字段或数组中。

  • 下面总结基本类型的加载。

Java 虚拟机的算数运算几乎全部依赖于操作数栈。也就是说需要将堆中的 boolean,byte,char 以及 short 加载到操作数栈上,而后将栈上的值当做 int 类型来运算。

对于 boolean 和 char 这两个无符号类型,加载伴随着零扩展。举例:char 大小为两个字节,加载时 char 的值会复制到 int 类型的低二字节,而高二字节则会用 0 来填充。

对于 byte 和 short 这两个类型来说,加载伴随着符号的扩展。举例:short 的大小为两个字节,加载时同样会将值复制到 int 类型的低二字节。如果 short 的值为非负数,即最高位为 0,那么 int 类型的值的高二字节会用 0 来填充,否则用 1 来填充。

扩展思考

public class Foo {
static boolean boolValue; public static void main(String[] args) {
boolValue = true; // 将这个 true 替换为 2 或者 3,再看看打印结果
if (boolValue)
System.out.println("Hello, Java!");
if (boolValue == true)
System.out.println("Hello, JVM!");
}
}

分析上述代码第一打印结果,以及将 true 替换成 2 或者 3 的时候,打印结果又是什么。

第一次打印:(条件:boolValue = true)
Hello, Java!
Hello, JVM! 第二次打印:(条件:boolValue = 2) 第三次打印:(条件:boolValue = 3)
Hello, Java!
Hello, JVM!

原因是:boolean 保存在静态域中,制定了它的类型。为了保证堆中 boolean

值的合法性, HotSpot 在存储时显示地进行掩码操作,也就说说只取低位 (最后一位) 的值存入 boolean 字段或数组中。即:当 boolValue = 2 的时候,取最后一位值为 0 代表 false,当 boolValue = 3 的时候,取最后一位值为 1 代表 true。

问答

Q:为什么 boolean,byte,char 以及 short 在栈中存储的时候占用四个字节

变长数组不好控制,所以牺牲空间换取效率。

Q:基本类型在内存中默认值都是0,那么是如何区别是哪种类型数据的呢?

内存中不做区分,Java 程序想把它解读成什么类型,它就是什么类型。

Q:double 和 long 占用两个数组单位,64位的机器上,数组单位是8个字节,也就是说在解释栈上面它们占用了16个字节?

是的。占用但并没有用高八字节的空间。这个属于HotSpot的实现细节,偏向了快速访问而牺牲了耗费空间。

Q:使用基本类型能够在执行效率以及内存使用两方面提升软件性能?具体是什么原理呢?

占的空间更小,不需要类型转换。

总结

本文创作灵感来源于 极客时间 郑雨迪老师的《深入拆解 Java 虚拟机》课程,通过课后反思以及借鉴各位学友的发言总结,现整理出自己的知识架构,以便日后温故知新,查漏补缺。

关注本人公众号,第一时间获取最新文章发布,每日更新一篇技术文章。

02 Java 的基本类型的更多相关文章

  1. 016 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 10 布尔类型和字符串的字面值

    016 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 10 布尔类型和字符串的字面值 本文知识点:字面值 关于字面值的概念,需要注意:很多地方,我们可能就把字面值 ...

  2. 010 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 04 变量的三个元素的详细介绍之二——变量类型——即Java中的数据类型

    010 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 04 变量的三个元素的详细介绍之二--变量类型--即Java中的数据类型 Java中变量的三要素 变量名 变 ...

  3. 02 java包装类型的缓存机制

    02 java包装类型的缓存机制 Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能. Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,12 ...

  4. 关于java中Double类型的运算精度问题

    标题     在Java中实现浮点数的精确计算    AYellow(原作) 修改    关键字     Java 浮点数 精确计算   问题的提出:如果我们编译运行下面这个程序会看到什么?publi ...

  5. 关于java中Double类型的运算精度问题(转)

    Java Java double:浮点数:精确计算  public class Test{    public static void main(String args[]){        Syst ...

  6. Java-Runoob-高级教程-实例-方法:02. Java 实例 – 输出数组元素

    ylbtech-Java-Runoob-高级教程-实例-方法:02. Java 实例 – 输出数组元素 1.返回顶部 1. Java 实例 - 输出数组元素  Java 实例 以下实例演示了如何通过重 ...

  7. 205K+程序员关注过的问题:为什么不应该使用Java的原始类型?

    在逛 Stack Overflow 的时候,发现了一些访问量像熊耳山一样高的问题,比如说这个:为什么不应该使用Java的原始类型?访问量足足有 205K+,这不得了啊!说明有很多很多的程序员被这个问题 ...

  8. 02 java语言基础

    常量:字面值常量(字符串,字符,整数,小数,布尔,null),自定义常量,''这个不是字符常量,""这个是字符串常量 进制: 02.01_Java语言基础(常量的概述和使用) A: ...

  9. [02]java数据类型和运算符等知识

    00 Java中的注释 为了方便程序的阅读,Java语言允许程序员在程序中写上一些说明性的文字,用来提高程序的可读性,这些文字性的说明就称为注释.注释不会出现在字节码文件中,即Java编译器编译时会跳 ...

随机推荐

  1. 爬去豆瓣图书top250数据存储到csv中

    from lxml import etree import requests import csv fp=open('C://Users/Administrator/Desktop/lianxi/do ...

  2. cdoj 414 八数码 (双向bfs+康拓展开,A*)

    一道关乎人生完整的问题. DBFS的优越:避免了结点膨胀太多. 假设一个状态结点可以扩展m个子结点,为了简单起见,假设每个结点的扩展都是相互独立的. 分析:起始状态结点数为1,每加深一层,结点数An ...

  3. FreeRTOS笔记

    任务的创建和删除(静态方法) 任务创建后要开启调度器. FreeRTOSConfig.h 1. 改宏 使能静态创建函数. 会出现,有两个函数未定义. Cortex-M中断管理(上) NVIC:嵌套向量 ...

  4. HTML_5 (1 2 3的代码总结)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. python_94_类变量实例变量

    class Role: n=123#类变量 name='我是类name' list=[] def __init__(self,name,role,weapon,life_value=100,money ...

  6. vue跨域处理(vue项目中baseUrl设置问题)

    1.开发环境: 2.生产环境: 然后 const instance = axios.create({ baseURL: process.env.API })

  7. idea中pom.xml没有工作 IDEA中maven项目pom.xml依赖不生效解决

    问题: 今天在web项目中需要引入poi相关jar包.查看之下才发现pom.xml中的依赖虽然已经下载到了本地仓库 repository,但是却没有加入到项目路径的 Extenal Libraries ...

  8. Oracle Real Application Clusters (RAC)

    Oracle Real Application Clusters — 概述 包含 Oracle Real Application Clusters (RAC) 选件的 Oracle 数据库允许依托一组 ...

  9. 最大长度回文子串(Manacher's algorithm)

    输出最大长度的回文子串. string longestPalindrome(string s) { int id, mx, i, j, len, maxlen; vector<char> ...

  10. cocos2d-x中的字符串操作

    1:循环体中字符串的构造.      通常用于多个有规律的文件的名字,诸如:[NSString stringWithFormat:@"filed.png",i].我们可以通过spr ...