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编译器编译时会跳 ...
随机推荐
- IT圈网红,抢鲜围观
即将于2017年10月23-26日,在北京举办的微软技术暨生态大会,是微软中国年度最盛大的科技峰会,是微软技术大会与合作伙伴大会的首次联袂,也是聚集众多IT大咖的技术狂欢派对. 无论你想实现现代化工作 ...
- jsp之初识UserBean
package com.java.model; public class Student { private String name; private int age; public String g ...
- POJ 2923 Relocation(01背包+状态压缩)
题意:有人要搬家,有两辆车可以运送,有若干家具,车有容量限制,而家具也有体积,那么如何运送会使得运送车次最少?规定两车必须一起走,两车一次来回只算1躺. 思路:家具怎么挑的问题,每趟车有两种可能:1带 ...
- 洛谷 P2002 消息扩散
题目背景 本场比赛第一题,给个简单的吧,这 100 分先拿着. 题目描述 有n个城市,中间有单向道路连接,消息会沿着道路扩散,现在给出n个城市及其之间的道路,问至少需要在几个城市发布消息才能让这所有n ...
- Ubuntu下apt-get与pip安装命令的区别
在ubuntu服务器下安装包的时候,经常会用到sudo apt-get install 包名 或 sudo pip install 包名,那么两者有什么区别呢? 1.区别pip用来安装来自PyPI(h ...
- MyEclipse7.0 M1下载和注册码
首先介绍下,这款MyEclipse7.0 M1已经内置了Eclipse3.4,所以无需再去下载. 1.下载地址: http://downloads.myeclipseide.com/downloads ...
- CPP-基础:有关调用约定
在C语言中,假设咱们有这样的一个函数:int function(int a,int b) 调历时只有用result = function(1,2)的方法就能利用这个函数.然而,当高档语言被编译成计算机 ...
- Understanding NFS Caching
Understanding NFS Caching Filesystem caching is a great tool for improving performance, but it is im ...
- lua 分割字符串
-- 参数:待分割的字符串,分割字符 -- 返回:子串表.(含有空串) function split(str, split_char) local sub_str_tab = {} while tru ...
- C# 用qq邮箱发邮件
一.在企业的QQ邮箱中开启POP3/SMTP服务 开启服务时,授权密码保存好. 二.示例 public static string UserName = ""; // 企业邮箱 p ...