基本数据类型

Posted learning ing ing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基本数据类型相关的知识,希望对你有一定的参考价值。

基本数据类型

文章目录


前言

基本数据类型共8类,byte、short、int、long、float、double、char、boolean。


1.类型

整数型:byte、short、int、long
浮点型:float、double
字符型:char
布尔型:boolean

2.存储空间、表数范围、精度

byteshortintlongfloatdoublecharboolean
存储空间1248482
表数范围-128~127-215 ~ 215-1-231 ~ 231-1-263 ~ 263-1-3.403E38 ~ 3.403E38-1.798E308 ~ 1.798E308true/false
精度714

注意,虽然long的长度大于float的长度,但long的表数范围并没有float的表数范围大,是因为float采用的科学计数法来存储数据的。

3.整数型

包含4种,byte、short、int、long。

  • java的整型常量默认为int型
  • java程序中变量通常声明为int型,除非不足以表示较大的数,才使用long
  • 声明long型常量,后面须加“l”或“L”

4.浮点型

包含2种,float、double。float,单精度,尾数可以精确到7位有效数字。很多情况下,精度很难满足需求。double,双精度,精度是float的两倍。通常采用此类型。

  • Java 的浮点型常量默认为double型 型,明 声明float 型常量,须后加‘f’ 或‘F’ 。

浮点型通常有两种表现形式:
1.十进制数形式:如:5.12 512.0f .512 (必须有小数点)
2.科学计数法形式:如:5.12e2 512E2 100E-2

4.1.浮点型float底层存储原理

4.1.1.十进制转二进制

整数部分直接转成二进制。小数部分一直乘以2,小于1则用结果继续乘,大于1则结果减1继续乘,等于1则结束,小于1即为0,大于1即为1。

4.1.2.float类型位图介绍

  • sign,用1位来表示浮点数正负,0表示正数;1表示负数。
  • exponent,用8位表示二进制的科学计数法中的指数部分的值,8位表示的数据范围可以是0 ~ 255,但是由于指数部分可能为负数,所以这个指数的范围为-128 ~ 127。再计算时让【指数+127】得到值转换为二进制存储在此即可。

注:0.5375的二进制小数位0.10001,科学计数法为 1.0001 * 2^-1。

  • fraction,用32为来表示二进制小数的科学计数法中的小数部分(不管整数部分,因为科学计数法中的整数总是为 1)。

4.1.3.39.29 转换为二进制过程

// 整数部分 39
100111

// 小数部分 0.29
0.29 * 2 = 0.58; // 0 小于1,则继续乘
0.58 * 2 = 1.16; // 1 大于1,则减1继续乘
0.16 * 2 = 0.32; // 0 小于1,则继续乘
0.32 * 2 = 0.64; // 0 小于1,则继续乘
0.64 * 2 = 1.28; // 1 大于1,则减1继续乘
0.28 * 2 = 0.56; // 0 小于1,则继续乘
0.56 * 2 = 1.12; // 1 大于1,则减1继续乘
0.12 * 2 = 0.24; // 0 小于1,则继续乘
0.24 * 2 = 0.48; // 0 小于1,则继续乘
0.48 * 2 = 0.96; // 0 小于1,则继续乘
0.96 * 2 = 1.92; // 1 大于1,则减1继续乘
0.92 * 2 = 1.84; // 1 大于1,则减1继续乘
0.84 * 2 = 1.68; // 1 大于1,则减1继续乘
0.68 * 2 = 1.36; // 1 大于1,则减1继续乘
0.36 * 2 = 0.72; // 0 小于1,则继续乘
0.72 * 2 = 1.44; // 1 大于1,则减1继续乘
0.44 * 2 = 0.88; // 0 小于1,则继续乘
0.88 * 2 = 1.76; // 1 大于1,则减1继续乘
0.76 * 2 = 1.52; // 1 大于1,则减1继续乘
0.52 * 2 = 1.04; // 1 大于1,则减1继续乘
0.04 * 2 = 0.08; // 0 小于1,则继续乘
0.08 * 2 = 0.16; // 0 小于1,则继续乘
0.16 * 2 = 0.32; // 0 小于1,则继续乘(与第三行相同,这样会一直循环执行下去)
。。。
将相乘之后的结果的整数部分拼接起来,所以0.29 的二进制表示:01001010001111010111000...

  • 结果:10111.01001010001111010111000…
  • 科学计数法:1.011101001010001111010111000… * 25
  • sign = 0,浮点数为正数。
  • exponent = 01000010,指数 5 + 127 = 132,将132转换为二进制。
  • fraction = 00111010010100011110101,最多保留23为二进制小数位,其他省略(不精确)。
  • 所以,最终39.25在存储时的二进制为:0 01000010 00111010010100011110101

5.字符型

只有一种,char。用来表示通常意义上“字符”(2字节)。

  • Java中的所有字符都使用Unicode编码,故一个字符可以存储一个字母,一个汉字,或其他书面语的一个字符。
  • char类型是可以进行运算的。因为它都对应有Unicode码。例如:
// 字符'a'的Unicode码值为97
char c = 'a';
int i = c + 1;
System.out.println("i=" + i);
>>> i=98

字符型变量的三种表现形式:
1.字符常量是用单引号(‘ ’)括起来的单个字符。例如:char c1 = ‘a’; char c2= ‘中’; char c3 = ‘9’;
2.Java中还允许使用转义字符‘\\’来将其后的字符转变为特殊字符型常量。例如:char c3 = ‘\\n’; // '\\n’表示换行符。
3.直接使用 Unicode 值来表示字符型常量:‘\\uXXXX’。其中,XXXX代表一个十六进制整数。如:\\u000a 表示 \\n。

6.布尔型

boolean 类型用来判断逻辑条件,一般用于程序流程控制。boolean类型数据只允许取值true和false,无null。

  • 不可以使用0或非 0 的整数替代false和true,这点和C语言不同。
  • Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达所操作的boolean值,在编译之后都使用java虚拟机中的int数据类型来代替:true用1表示,false用0表示。(取自《java虚拟机规范 8版》)

7.基本类型转换

基本数据类型之间的转换规则。

7.1.自动类型转换

容量小的类型自动转换为容量大的数据类型。数据类型按容量大小排序为:

  • 有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。
  • byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。
  • boolean类型不能与其它数据类型运算。
  • 当把任何基本数据类型的值和字符串(String)进行连接运算时(+),基本数据类型的值将自动转化为字符串(String)类型。

7.2.强制类型转换

自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符:(),但可能造成精度降低或溢出,格外要注意。

  • 通常,字符串不能直接转换为基本类型,但通过基本类型对应的包装类则可以实现把字符串转换成基本类型。如: String a = “43”; int i = Integer.parseInt(a);
  • boolean类型不可以转换为其它的数据类型。

基本数据类型和引用数据类型的区别

1、基本数据类型和引用数据类型

  ECMAScript包括两个不同类型的值:基本数据类型和引用数据类型。

  基本数据类型指的是简单的数据段,引用数据类型指的是有多个值构成的对象。

  当我们把变量赋值给一个变量时,解析器首先要确认的就是这个值是基本类型值还是引用类型值。

2、常见的基本数据类型:

  Number、String 、Boolean、Null、Undefined和Symbol。基本数据类型是按值访问的,因为可以直接操作保存在变量中的实际值。示例:

 var a = 10;

 var b = a;

 b = 20;

 console.log(a); // 10值

上面,b获取的是a值得一份拷贝,虽然,两个变量的值相等,但是两个变量保存了两个不同的基本数据类型值。

b只是保存了a复制的一个副本。所以,b的改变,对a没有影响。

3、引用类型数据:

也就是对象类型Object type,比如:Object 、Array 、Function 、Data等。

javascript的引用数据类型是保存在堆内存中的对象。

与其他语言的不同是,你不可以直接访问堆内存空间中的位置和操作堆内存空间。只能操作对象在栈内存中的引用地址。

所以,引用类型数据在栈内存中保存的实际上是对象在堆内存中的引用地址。通过这个引用地址可以快速查找到保存中堆内存中的对象。  

var obj1 = new Object();

var obj2 = obj1;

obj2.name = "我有名字了";

console.log(obj1.name); // 我有名字了

在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量,也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的改变都会反映在另一个身上。

4、总结区别

a 声明变量时不同的内存分配: 

1)原始值:存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。这是因为这些原始类型占据的空间是固定的,所以可将他们存储在较小的内存区域 – 栈中。这样存储便于迅速查寻变量的值。

2)引用值:存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。这是因为:引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。

b 不同的内存分配机制也带来了不同的访问机制
1)在javascript中是不允许直接访问保存在堆内存中的对象的,所以在访问一个对象时,首先得到的是这个对象在堆内存中的地址,然后再按照这个地址去获得这个对象中的值,这就是传说中的按引用访问
2)而原始类型的值则是可以直接访问到的。
c 复制变量时的不同
1)原始值:在将一个保存着原始值的变量复制给另一个变量时,会将原始值的副本赋值给新变量,此后这两个变量是完全独立的,他们只是拥有相同的value而已。
2)引用值:在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量,也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的改变都会反映在另一个身上。
d 参数传递的不同(把实参复制给形参的过程
首先我们应该明确一点:ECMAScript中所有函数的参数都是按值来传递的。
但是为什么涉及到原始类型与引用类型的值时仍然有区别呢?还不就是因为内存分配时的差别。  
1)原始值:只是把变量里的值传递给参数,之后参数和这个变量互不影响。
2)引用值:对象变量它里面的值是这个对象在堆内存中的内存地址,因此它传递的值也就是这个内存地址,这也就是为什么函数内部对这个参数的修改会体现在外部的原因了,因为它们都指向同一个对象。
 
参考资料:
https://www.cnblogs.com/cxying93/p/6106469.html

 

以上是关于基本数据类型的主要内容,如果未能解决你的问题,请参考以下文章

JVM之数据类型

java数据类型

JVM堆与JVM栈

java的8种基本数据类型为什么叫基本数据类型

java虚拟机JVM

jvm调优