Java的八种基本数据类型
基本数据类型
Java语言提供了八种基本类型。
基本数据类型:数值型、字符型、布尔型。
数值型:整数型byte、short、int、long
浮点型:float、double
byte:
byte数据类型是8位、有符号的,以二进制补码表示的整数;(256个数字),占1字节
最小值是-128(-2^7);
最大值是127(2^7-1);
默认值是0;
byte类型用在大型数组中节约空间,主要代替整数,因为byte变量占用的空间只有int类型的四分之一;
short:
short数据类型是16位、有符号的以二进制补码表示的整数,占2字节
最小值是-32768(-2^15);
最大值是32767(2^15 - 1);
Short数据类型也可以像byte那样节省空间。一个short变量是int型变量所占空间的二分之一;
默认值是0;
int:
int数据类型是32位、有符号的以二进制补码表示的整数;占4字节
最小值是-2,147,483,648(-2^31);
最大值是2,147,485,647(2^31 - 1);
一般地整型变量默认为int类型;
默认值是0;
long:
long数据类型是64位、有符号的以二进制补码表示的整数;占8字节
最小值是-9,223,372,036,854,775,808(-2^63);
最大值是9,223,372,036,854,775,807(2^63 -1);
这种类型主要使用在需要比较大整数的系统上;
默认值是0L;
这里需要注意的是在定义long时,数值大于int的规定最大值会受检报错,需要在数字的尾部加上l。
空间占用
在实际操作中,空间大小又分为两类:
1、理论规定大小。
2、JVM的真实大小。
开辟内存空间发生在变量定义时,且与储存的内容无关,只与数据类型有关。不同的数据类型存同样的数据,所占用的内存是不同的。
这是理论上的图示:
但是在JVM在字节码层面上支持的整数类型确实只有int和long,所有比int小的整数类型都会被提升为int来运算。
(但是在JVM的数组byte[],和short[]中,每个元素是真正的1字节和2字节,我们继续往下看)
所以在Java中byte,short并不会起到提高效率的作用,两者和int的效率基本是一样的。(但数组byte[]、short[]会起到提高效率的作用)。
java虚拟机对byte、char和short的处理方式(转载)
java字节码中的大部分指令都没有支持整数类型byte、char和short,甚至没有任何指令支持boolean类型,编译器会在编译期或者运行期将byte和short类型的数据带符号扩展为相应的int类型的数据,将boolean和char类型数据零位扩展为相应的int类型数据,与之类型,在处理boolean、byte、short和char类型的数组时,也会转换为使用对应的int类型的字节码指令来处理,因此,大多数对于boolean、byte、short和char类型数据的操作,实际上都是使用相应的int类型作为运算类型
多余定义变量会浪费空间
而只有数组byte[]才会是真正是1字节,short[]是2字节。
此外,定义变量而不使用,是一种浪费空间的行为,Java的编译器会建议你删掉没有使用的变量
目前,我们计算机的内存越来越多。对于常规的定义大多使用int方法,从便利上已满足需要。
但在一些大型程序如游戏的开发中,为了追求极致而节省空间。就会采用相近合适的数据类型来存储数据。
下面,我们来看一看不同数据类型的变量在创建时的内存使用情况。
运行时观看内存情况
注意:byte类型虽然在语义(逻辑)上是占用1字节,但实际上,JVM中是将其当做int看的,也就是事实上是占用了32位,4字节的,所以其运算效率和int没区别。
之所以要有byte/short类型,一是因为某些地方要明确使用这些范围类型,
二是,在byte[]数组中,JVM存储的则是真的1字节,short[]2字节。(但也有的JVM其byte[]数组也是4字节1位)
这种规定与真实的差异是由JVM翻译所造成的。
下面,我们使用Java库的方法来查看内存的使用。
为了使变化更明显,我们定义了一个较大的二维数组来观看:
用int来定义二维数组:
使用内存5833KB
由byte数据类型来创建二维数组:
使用内存2582KB
由于,程序在启动时,还有其他的加载项。所以byte与int并没有呈现严格的4倍关系。
以上,就是不同数据类型的数组开辟内存空间所带来的差异。(考虑到JVM,以上情况仅适用于数组)
以及存储数据并不会带来空间上的变化。
整型间的数字类型转换:
Java中数据类型转换分为自动类型转换和强制类型转换
什么叫做自动转换?
自动转换
小水杯向大水杯倒,不需要进行额外进行操作
强制类型转换
从大类型向小类型,可能会溢出出现错误。
代码中会提示错误,所以要加上强制类型转换
byte b = 127; int i = b;//自动转换
b = (byte)i;//强制转换有可能导致精度丢失。
强制类型转换精度丢失如图所示:
我们知道byte的范围是 -128~127
a=128超出了byte正数的范围,所以b以-128为起始重新开始相加
利用这个特点,在一定情况下可以利用byte反推出int的值(虽然应该用不到)
也可以从二进制数来区分数据类型的大小:
这里boolean类型虽然只有一个二进制数,但仍然和byte一样,占一个字节。(JVM会将boolean翻译成int类型,会占用4个字节。byte和short上面已经提到,char稍后讨论)
浮点型
float
float属于Java中的浮点型,也叫单精度浮点型,长度为4字节32bit,变量初始化默认值0.0f,包装类Float
double
double属于Java中的浮点型,也叫双精度浮点型,长度为8字节64bit,变量初始化默认值0.0d,包装类Double
当整型转向浮点型时要进行强制类型转换
int a = 10;
float b = 10.1f;
a = (int) b;
目前double的使用比较频繁。
字符型
char类型是一个单一的16位Unicode字符;用 ‘’表示一个字符。java 内部使用Unicode字符集,它有一些转义字符 ,2字节
最小值是’\u0000’(即为0);
最大值是’\uffff’(即为65,535);可以当整数来用,它的每一个字符都对应一个数字
字符型相加会按顺序执行,强制转换成int类型会输出对应的ascii码
同样,汉字也可以通过字符相加进行变动。以部首和笔画为顺序
需要注意的是,char类型在虚拟机中也是转换为int类型。
boolean类型
boolean数据类型表示一位的信息;
只有两个取值:true和false;
这种类型只作为一种标志来记录true/false情况;
默认值是false;
boolean的大小(转载)
1、1个bit
理由是boolean类型的值只有true和false两种逻辑值,在编译后会使用1和0来表示,这两个数在内存中只需要1位(bit)即可存储,位是计算机最小的存储单位。
2、1个字节
理由是虽然编译后1和0只需占用1位空间,但计算机处理数据的最小单位是1个字节,1个字节等于8位,实际存储的空间是:用1个字节的最低位存储,其他7位用0填补,如果值是true的话则存储的二进制为:0000 0001,如果是false的话则存储的二进制为:0000 0000。
3、4个字节
理由来源是《Java虚拟机规范》一书中的描述:“虽然定义了boolean这种数据类型,但是只对它提供了非常有限的支持。在Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达式所操作的boolean值,在编译之后都使用Java虚拟机中的int数据类型来代替,而boolean数组将会被编码成Java虚拟机的byte数组,每个元素boolean元素占8位”。这样我们可以得出boolean类型占了单独使用是4个字节,在数组中又是1个字节。
显然第三条是更准确的说法,那虚拟机为什么要用int来代替boolean呢?为什么不用byte或short,这样不是更节省内存空间吗。大多数人都会很自然的这样去想,我同样也有这个疑问,经过查阅资料发现,使用int的原因是,对于当下32位的处理器(CPU)来说,一次处理数据是32位(这里不是指的是32/64位系统,而是指CPU硬件层面),具有高效存取的特点。
可以看出,boolean类型没有给出精确的定义,《Java虚拟机规范》给出了4个字节,和boolean数组1个字节的定义,具体还要看虚拟机实现是否按照规范来,所以1个字节、4个字节都是有可能的。这其实是运算效率和存储空间之间的博弈,两者都非常的重要。