02 Java 的基本类型
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 的基本类型的更多相关文章
- 016 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 10 布尔类型和字符串的字面值
016 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 10 布尔类型和字符串的字面值 本文知识点:字面值 关于字面值的概念,需要注意:很多地方,我们可能就把字面值 ...
- 010 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 04 变量的三个元素的详细介绍之二——变量类型——即Java中的数据类型
010 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 04 变量的三个元素的详细介绍之二--变量类型--即Java中的数据类型 Java中变量的三要素 变量名 变 ...
- 02 java包装类型的缓存机制
02 java包装类型的缓存机制 Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能. Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,12 ...
- 关于java中Double类型的运算精度问题
标题 在Java中实现浮点数的精确计算 AYellow(原作) 修改 关键字 Java 浮点数 精确计算 问题的提出:如果我们编译运行下面这个程序会看到什么?publi ...
- 关于java中Double类型的运算精度问题(转)
Java Java double:浮点数:精确计算 public class Test{ public static void main(String args[]){ Syst ...
- Java-Runoob-高级教程-实例-方法:02. Java 实例 – 输出数组元素
ylbtech-Java-Runoob-高级教程-实例-方法:02. Java 实例 – 输出数组元素 1.返回顶部 1. Java 实例 - 输出数组元素 Java 实例 以下实例演示了如何通过重 ...
- 205K+程序员关注过的问题:为什么不应该使用Java的原始类型?
在逛 Stack Overflow 的时候,发现了一些访问量像熊耳山一样高的问题,比如说这个:为什么不应该使用Java的原始类型?访问量足足有 205K+,这不得了啊!说明有很多很多的程序员被这个问题 ...
- 02 java语言基础
常量:字面值常量(字符串,字符,整数,小数,布尔,null),自定义常量,''这个不是字符常量,""这个是字符串常量 进制: 02.01_Java语言基础(常量的概述和使用) A: ...
- [02]java数据类型和运算符等知识
00 Java中的注释 为了方便程序的阅读,Java语言允许程序员在程序中写上一些说明性的文字,用来提高程序的可读性,这些文字性的说明就称为注释.注释不会出现在字节码文件中,即Java编译器编译时会跳 ...
随机推荐
- 爬去豆瓣图书top250数据存储到csv中
from lxml import etree import requests import csv fp=open('C://Users/Administrator/Desktop/lianxi/do ...
- cdoj 414 八数码 (双向bfs+康拓展开,A*)
一道关乎人生完整的问题. DBFS的优越:避免了结点膨胀太多. 假设一个状态结点可以扩展m个子结点,为了简单起见,假设每个结点的扩展都是相互独立的. 分析:起始状态结点数为1,每加深一层,结点数An ...
- FreeRTOS笔记
任务的创建和删除(静态方法) 任务创建后要开启调度器. FreeRTOSConfig.h 1. 改宏 使能静态创建函数. 会出现,有两个函数未定义. Cortex-M中断管理(上) NVIC:嵌套向量 ...
- HTML_5 (1 2 3的代码总结)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- python_94_类变量实例变量
class Role: n=123#类变量 name='我是类name' list=[] def __init__(self,name,role,weapon,life_value=100,money ...
- vue跨域处理(vue项目中baseUrl设置问题)
1.开发环境: 2.生产环境: 然后 const instance = axios.create({ baseURL: process.env.API })
- idea中pom.xml没有工作 IDEA中maven项目pom.xml依赖不生效解决
问题: 今天在web项目中需要引入poi相关jar包.查看之下才发现pom.xml中的依赖虽然已经下载到了本地仓库 repository,但是却没有加入到项目路径的 Extenal Libraries ...
- Oracle Real Application Clusters (RAC)
Oracle Real Application Clusters — 概述 包含 Oracle Real Application Clusters (RAC) 选件的 Oracle 数据库允许依托一组 ...
- 最大长度回文子串(Manacher's algorithm)
输出最大长度的回文子串. string longestPalindrome(string s) { int id, mx, i, j, len, maxlen; vector<char> ...
- cocos2d-x中的字符串操作
1:循环体中字符串的构造. 通常用于多个有规律的文件的名字,诸如:[NSString stringWithFormat:@"filed.png",i].我们可以通过spr ...