Java基础-基础数据类型(8种)
此文是我边想边问自己,被问住了就去查,将自己的理解写下来的。如果您看不懂那一定是我的问题,可能我写的时候也在迷糊。如果有不对的地方还请评论留言指正,感谢路过的大佬!!!
摘要
如果你会小学数学中的未知数,那么我觉得我能带你入门。
“数据类型”看起来好像很唬人,但是没什么难的。
基础数据类型
数据类型 | 关键字 | 位数(比特位) | 默认值 | 取值范围 |
---|---|---|---|---|
字符类型 | char | 16 | 空 | 0 ~ 2^15-1 |
布尔类型 | boolean | 8 | true | true,false |
整数类型 | byte | 8 | 0 | -2^7 ~ 2^7-1 |
短整型 | short | 16 | 0 | -2^15 ~ 2^15-1 |
整数类型 | int | 16 | 0 | -2^31 ~ 2^31-1 |
长整型 | long | 32 | 0L | -2^63 ~ 2^63-1 |
浮点型 | float | 32 | 0.0f | -2^31 ~ 2^31-1 |
浮点型 | double | 64 | 0.0d | -2^63 ~ 2^63-1 |
这个表格网上一搜就有,我会尽可能详尽的讲解
位数,即比特位。可能会有的人觉得陌生什么意思(基础没打好的)
那么MB知道吧,文件大小的MB、GB知道吧。
位和他们是一伙的。
位 也叫 比特位,B数据存储的最小单位。
二进制数)的一位所包含的信息就是一比特,如二进制数0100就是4比特(引用自百度百科)。
换算:
1 B = 1 byte (字节)
1 KB = 1024 B(字节);
1 MB = 1024 KB; (2^10 B)
1 GB = 1024 MB; (2^20 B)
1 TB = 1024 GB; (2^30 B)
下面开始带你入门
为什么我说会未知数就会这个呢
未知数x,一元一次方程。加入有个式子x+1=2那么x的值是多少?
x+1=2
x=2-1
x=1
所以答案是x=1
那么这是不是一种表达方式,x=1表达出的意思是x的值是1
那么其实在Java编程中,定义一个“未知数”的值是多少也是这样的形式
x=1 //他的意思就是x的值为1
那么如果是英语老师让你做卷子,有一道单词补全的题:
_____________va
那么前面这一句是什么?很明显我们都被过是“Ja”啊对不对。
那么前面空出来的这一段又何尝不是一个未知数呢,那么是不是也可以定义一个y="Ja"呢
其实这两个定义都符合Java的要求
好,我们知道一件事,发现了一件事
知道的是:Java是老外发明的,语法上的东西肯定要用英语,而且英文字母、单词这些肯定是应为字母
发现的是:我有x=1和y=“Ja”
总结:x和y都可以使用在Java语法中,而且上面两种定义方式我也说都可以,但是一个是数字一个是字母组合,那么x和y所表达的数据的类型是不是不同,一个是数字,一个是英文字母的组合。其实这就是数据类型。
存储数据类型理解
char
char,字符类型,16位(2字节),它其实基于Unicode字符集标准,他可以表示大多数字符,包括字母、数字、阿拉伯文字、汉字等,下面是定义(专业词汇是叫:声明):
char x='a';
也可以是
char x='1';
那么提问:那么是否可以代表其他语种中的一个字符呢?比如中文、阿拉伯语、泰语、日语等
答:不一定,每种语言在不同的编码格式中一个字符所占用的字节数是不同的所以答案是不一定,需要有上下文条件。
提到两个新词或:字符集,编码格式(后期加超链接,连接到新文章)
boolean
这个就比较简单了,它只有俩个值,true 或 false 即 真/是 或 假/否。这部分数学知识咱那讲的忘了,举一个通用的例子吧:
判断 | 结果 | boolean值 |
---|---|---|
1 是否大于 0 | 是 | true |
1 是否大于 2 | 否 | flase |
byte
这个类型存储的其实是二进制数据,他不是占8个比特位吗,那不就是一个字节嘛,byte类型的数据是8位带符号的二进制数。就像是电影中的黑客电影一样,电脑屏幕上满是0和1的组合,Java中传输数据是要将数据转成二进制数据进行传输的。后续接触IO相关概念时还会用的到这个数据类型。
short-int-long
这三个都是整数类型,所以放一块讲,也方便记忆。
什么是整数,1、2、3、4、5、6、-1、-2、-3.。。。。这种没有小数位的就是整数呗
只不过是short可以表示的数字范围最小,long可以表示的范围最大,而int范围中等
float-double
浮点数类型,这个就是可以表示小数位的数据类型了,区别是float能表示的小数位数比double能表示是的小数位数要小。
底层存储
聊之前大家要知道一个事情,就是计算机底层其实处理的都是0和1,这些数据类型的第曾存储也是这样,只不过处理成了方便我们看得懂的形式。
解疑
为什么一个字节是8位,但是为什么给的取值范围却是7次方15次方这种非8的倍数呢?
答:这8位中的第一位表示这个数字的正负,也就是为什么取值是一个范围,是一个从负到正的范围。
char
其实char底层也是0和1组成的二进制,那么ta为什么能表示一个字符呢,那么就要提一下之前提到的Unicode了,他是一个汇聚全球多种语言的字符字典表,而且是有顺序有标号的,所以char只需要使用二进制表示目标字符在Unicode表中的标号或者说是位置不就可以让一个char代表一个字符了吗。
而char的取值范围也是依据了Unicode表,我们希望char能够表示Unicode中的每一个字符,所以取值范围要比Unicode中收集的字符的数量高,所以取了这么一个值。
以下仅为举例并不是真实Unicode表:
字符: | a | b | c | d | e | 一 | … |
---|---|---|---|---|---|---|---|
码点(正式叫法) | 0 | 1 | 2 | 3 | 5 | 6 | … |
char x = ‘a’ ,那么底层为 char x = 00000000 00000000
解析则是通过 char x = 00000000 00000000 找到 对应的字符是 ’a‘
char和Unicode表和字符集编码的关系:
char和Unicode表是映射关系,char的数值 对应 Unicode表中的字符
而Unicode表不是一成不变的,因为一次性收集到全球所有的字符不太现实,它是一直在扩大的,如今Unicode表的容量早已远远超出了char的取值范围,那么这如何让char和Unicode表中的字符做映射呢?
此时字符集编码就出场了,它的作用就是让char以某种形式去表示Unicode表中码点超出char表示范围的部分,具体的方式我就不太了解了,感兴趣的朋友可以自己查一下(顺便发给我,偷懒一手),不同的字符集编码处理这个问题的形式也不一样,这也是为什么同一个字符在不同的字符集编码下所占用的内存大小不同,但都会处理成char可以表示的形式。
byte
byte本身存储的就是01表示的二进制,其实这已经很底层了,再底层就涉及一些底层硬件和通信协议了,而且大多数都将1字节作为最小单位,所以java规范为byte的取值范围为1字节(8位二进制)。
再往上层的话就是char的这一套映射逻辑了,毕竟这涉及到将Java数据转换为二进制流进行数据传输。
boolean
它其实只表示两个值:true 或者 false。那么其实底层我直接用1 表示true 用 0 表示false就行了,而且很节省内存空间,而且正好最底层肯定是 0 或 1,这多好。
但实际上却并不是,时间上会占用1个字节或者更多,一是因为计算机处理数据额度最小单位是1字节即8为二进制,二是可能由于JVM实现的不同在某种情况下可能会有区别。
额外:
但是,向上面这种 1表示true 0表示false的思想节约内存的思想是可以学习的。也就是自定义映射关系,就行char和Unicode一样,字典表/映射表中只需要记录一编占用内存的内容用在其他地方就可以使用节约内存代号就行了。
short-int-long
这三个底层都是二进制,但是每个类型所占用的字节数不同所以二进制位数也不同。
为什么给了三个类型呢,一个long不就全能表示了吗,long的范围最大?
确实,但是又回到了节约内存的问题,这么一说就明白了吧。就是为了让再不同场景下,既能满足业务需求又能一定程度上的介于内存空间,于是给了三个选择,找到一个效率和内存占用的最佳平衡点。
float-dubbo
先了解一下IEEE754标准
IEEE754标准是一种浮点数表示标准
一般分为单、双精度两种
单精度是32位的二进制数,双精度是64位的二进制数
一个浮点数的组成分为三个部分
第1位是数符s s=1表示负数 s=0表示正数
第2-9位为阶码E (双精度为2-12位)
第10-32位为尾数M (双精度为13-64位)
看不懂?
好,其实我也看不懂于是我去了解了一下
什么是数符、阶码、尾数和基数、
这样就开始涉及到标准中的词汇了
这是浮点型再计算机中俄的记录方式
如:
十进制中数字100.1231 = 0.1001231 * 10^3 ,0.0012 = 0.12 * 10^-2
那么二进制中数字 1010.1101 = 0.10101101 * 2^4 , 0.0010101101 = 0.10101101 * 2^-2
以0.10101101 * 2^-2为例 :
0.10101101这部分称之为尾数M
2^-2中前面的2称之为基数R,基数是固定值,看是多少进制
2^-2中后面的指数2称之为阶码E
2^-2中后面的2的正负符号称之为阶符,即E的正负符号
而基数2前面省略的符号称之为数符
小总结:学到这可以看出
阶码E决定范围
尾数R决定精度
现在下面这些就可以看懂了吧
float
类型遵循 IEEE 754 标准,使用 32 位(4 字节)来存储浮点数。这32位被分为三部分:
- 1位用于表示符号(0表示正数,1表示负数);
- 8位用于表示指数(以偏置形式存储,即实际指数加上一个固定的偏置值,对于
float
类型,偏置值是127); - 23位用于表示尾数(小数部分),实际上只表示24位,因为第一位隐含为1,不存储。
double
类型同样遵循 IEEE 754 标准,但使用 64 位(8 字节)来存储浮点数。这64位被分为三部分:
- 1位用于表示符号;
- 11位用于表示指数(偏置值为1023);
- 52位用于表示尾数(同样,第一位隐含为1,不存储)。
浮点类型进度丢失问题
我们知道了尾数是什么,知道了两个浮点数类型中各部分存储的是什么。
那么我们思考一个问题,如果正在处理一个数字,它的尾数的位数,超过了你选择的数据类型可以容纳尾数的位数,那么计算机会如何处理超出的部分,当然是抛弃掉,那么不就丢失了一部分精度了吗。很多例子都是0.9999999无限循环,那么它的尾数的位数不就一定超过了数据类型的限制了吗,那么不就是一定会出现精度丢失了吗。
扩展:
阶码:带符号的定点整数,常用移码和补码表示
尾数:带符号的定点小数,常用原码或补码表示
什么是补码
要深入计算机硬件计算层面了,计算机处理的是01两种信号,计算的是二进制数。
当使用二进制表达一个10进制时,有两种表达方式,一种叫“原码“一种叫”补码“
还有就是数字是有正负的
假设我要用一个8位1比特的二进制去表达10进制数字5,那么二进制是00001010
我们来分析一下这个10进制5的二进制原码表示
0 000 1010
最高位0表示这个二进制表达的是一个整数1则为负数,后面 000 1010则是表达10进制5的部分。
乍一看是没问题的,但是我查资料说使用原码表示确实直观简单,但是对于计算机对其做运算则是有问题的,例如加法(可以试一下-1+1是不是=-2),所以开发出了补码的表达形式。
补码的规则是这样的,整数原码的补码就是原码本身,而负数得到补码是原码按位取反后加1的值(注意最高位也参与按位取反)
来测试一下
5 = 00001010 按位取反为 11110101 再加1为1 0000 0101
加完后这里会进位一个1,但定长是8位,那么这个1就会被舍弃掉,所以结果会为 0000 0101
我们发现整数按位取反再加1结果和原码一样
再试一下负数
-5 10001010 按位取反为 01110101 再加1 为 01110110 ,这个就是-5的补码表示
什么是移码
一个二进制数不是有正负吗,是通过判断最高位是0还是1判断这个数是正是负,于是形成了一个坐标系负到正的范围,移码呢就是把坐标系负半轴的值移动到正半轴,需要移动多少次,例如需要移动3次即需要*23,那么这个23就是数字移动后的位置距离原来的位置的偏置值,移码就是移动后的值。
当然以上只是便于理解,其实就是将一个数字(不分正负)移动成整数需要成阶码的多少次幂
这一块我的理解可能有问题,还请路过的大佬指导纠正