8种类型概述
- 整型
byte
short
int
long
- 浮点型
float
double
- 布尔型
boolean
- 字符型
char
8种数据类型占用内存空间
现代计算机通过集成电路的电信号控制开关,只能识别0/1,例如0101000…,
十进制 0 1 2 3
二进制 0 1 10 11
而bit
是计算机可以识别的最小单位,表示二进制的0/1,有如下的换算关系:
1Byte(字节)= 8bit(比特位) = 8位的0/1
1Kb = 1024 Byte
1Mb = 1024 Kb
1Gb = 1024 Mb
1Tb = 1024 Gb
1Pb = 1024 Tb
1Zb = 1024 Pb
-
每种数据类型的存储空间,具体原理请参见下文
-
若声明类型时未赋值则8种数据类型的默认值都像0看齐
-
char 默认字符
\u0000
表示空字符(非空格) -
十进制和二进制转换
- 十进制转成二进制:
除2取余,逆序输出
- 十进制转成二进制:
2|6 0
2|3 0
2|1 1
2|0 1
12=1100=0*2^0+1*2+1*2^2+1*2^3
- 二进制转化成十进制
01111111=1*2^0+1*2^1+1*2^3+1*2^4+1*2^5+1*2^6+0*2^7=127
Java中的数字类型,数字都有正负之分,所以在二进制中有一个符号位,在二进制的最左边,0表示正数,1表示负数。
- 不同数据类型的取值范围的由来
byte类型为例,byte占8个比特位,最大值是0111 1111
,由前面可知换算成十进制是127
byte最小值是-128(和原码、反码和补码有关) - 其他进制
- 十进制 0 1 2 3 4 5 6 7 8 9
- 二进制 0 1 10 11 100…
- 八进制 0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20
- 十六进制 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20
- 处理字符
计算机善于处理计算关系,但现实中的文字和语言十分多样,计算机无法直接转化成二进制,需要人为的制定字符编码表:
计算机最初只支持英文,例如
‘a’ --97-- 01100001
‘A’ --65
‘0’ --48
‘a’ --按照ASII解码–> 01100001
01100001 --按照ASII编码–> ‘a’
当编码和解码采用同一种字典/对照表时,不会出现乱码
当编码和解码采用不同一种字典/对照表时,可能会出现乱码
字典的薄厚(不同的编码系统)决定了存储字符对应关系的多少:
- 中文编码:GBK2312< GBK <GB18030
- 全球编码unicode
- UTF-8:比较节省空间
- UTF-16
- UTF-32
- Java采用的是unicode编码,因此标志符可以使用中文(不建议使用)
字符型
- 字符型包括字符和字符串类型
- 字符通过
''
包裹,字符串通过""
包裹,二者不兼容,Java一个字符包括2个字节,而中文恰好是一个字符占2个字节,因此可以存储中文文字,例如char a = 'a'; char b = '帅'
,但是char a = "a"
不行,因为"a"
是字符串不能赋值到char
类型 - 通过
'\'
转义,转义字符也属于char
类型\n
System.out.print输出不换行,System.out.println换行\t
制表符\\
\
本身\'
'
本身\"
"
本身\u
\u
表示16进制的unicode编码\u4e2d
表示汉字“中” 可通过native2ascii命令将字符转换成16进制
整数型
-
Java语言中的“字面值”被默认当作
int
, 如果想要其变成long
需要在后面加上l/L
(建议L ) -
字面值可以以三种方式开始,但输出默认为十进制
- 10进制:常用
- 以0开头的8进制,010
- 以0x开头的16进制,0x10
-
类型自动转换
long x = 888
;//888 int字面值赋值给长整型的x,小容量可以自动转换成大容量long x = 2147483648
;//右边的值2147483648默认当作int,本身超出int 4个字节的容量,因此还未赋值给左边的long型就会导致错误(面试题目)long x = 2147483648L
;添加L使得变成long型
-
大容量无法自动转换成小容量数值,需要通过
(TYPE)
强制转换,但可能严重损失精度
long x = 100L;
//将100变为长整型并赋值给长整型x
int y = x;
//将长整型赋值给整型,小的存不了大的,转换失败,大容量无法自动转换成小容量
int y = (int) x;
//先强制将长整型x转换成整型再赋值给整型y,可能会丢失精度 -
大数转小数的时候为什么会损失精度?
这要从大数转小数的原理出发,例如int x = 100L
强制将8字节的长整型100转换成4个字节的整型,其过程如下
100L:00000000 00000000 00000000 00000000 00000000 00000000 00000000 01100100
要将其转换成4个字节的int
,计算机会从前面砍掉4个字节,因此剩下:
00000000 00000000 00000000 01100100
而该值换算后还是100,并未损失精度;
但是int x = 2147483648L
,按照同样的步骤转换:
2147483648L:00000000 00000000 00000000 00000000 10000000 00000000 00000000 00000000
,强制转换为4个字节的整型即截掉前面4个字节,此时剩下:
10000000 00000000 00000000 00000000
,很明显这是一个负数,实际上是-2147483648,可见损失精度之大 -
总结来说,若待转换的数据并未超过转换之后范围,是不会损失精度的,但是若超过了转换之后的范围,则可能严重损失精度
实际上,Java提供了更为便捷的数据类型自动转换方式,例如byte x = 56
,按照之前的知识,4个字节的int
是无法自动转换为1个字节的byte
的,但是只要不超过byte的取值范围-128~127
,该赋值语句完全可以;但是byte x = 128
则不合法,因为128已经超出了byte
的存储范围了
- 更一般的规律是,当整数字面值不超过
byte、short、char
的取值范围,这个字面值可以直接赋值给byte、short、char
,这是Java追求更为简洁的语法
public class DataType{
public static void main(String[] args){
// int x = 100L; //大数转小数报错
int x = (int) 100L; //加上(int)将100L强制转换为int,不会损失精度
System.out.println(x);
int y = (int) 2147483648L; //2147483648L已经超出待转换类型的范围,强制转换会严重损失精度
System.out.println(y);
byte i = 56; //支持byte类型的范围类大数转小数
System.out.println(i);
//bytj j = 128; //超出byte类型报错
byte j = (byte) 128; //强制转换严重损失精度
System.out.println(j);
char k = 32767; //不超过char的取值范围,编译通过
char m = (char) 32768; //超过char的取值范围,直接编译失败,强制转换损失精度
System.out.println(m);
}
}
浮点型
- 浮点型包括
float
和double
,分别占4个和8个字节,由于计算机内存有限,对于浮点型都是近似接近的。例如1/3=0.3333333333333…是无限循环小数,用有限的计算机内存资源存储无限的数据只能是近似的 - java对于所有浮点型字面值
1.0
会默认当作double
,不能直接赋值给float
类型,若想变成float
可以通过:- 1.通过
float
强制类型转换,可能会损失精度 - 2.直接在字面值后加上
F/f
- 1.通过
- 虽然
double
看似精度很高,但是对于财务领域依然不够(动辄百亿/千亿的资金若因为精度损失则会损失巨大),因此在java基础SE类库
中,提供了更高精度的java.math.BigDecimal
类库帮助运算,只不过它们属于引用的数据类型,不属于基础数据类型 类库
是前人已经编写好的专门处理某些特定领域问题的java代码,java强大之处正是因为可以基于这套庞大类库开发。我们使用的String[] args
实际上就是使用的String.class
- SE
类库
的字节码一般位于类似jdk-version-x/lib/*.jar/*.class
- SE
类库
的源码在类似jdk-version-x/src.zip
中的.java
源码
- SE
布尔型
- 布尔型
boolean
,在java中只有2个值true/false
,不像其他语言可以用1/0
表示,声明一个布尔型boolean age = true
- 布尔型主要是逻辑运算和条件判断,例如:
public class Bool{
public static void main(String[] args){
boolean age = false; //声明一个boolean类型false
if(age){
System.out.println("kids");//条件真则执行
}else{
System.out.println("adults");//条件假执行
}
}
}
类型转换规则
- 除了
boolean
,其他7种类型之间都可以相互转换 - 小数类型转大数类型时是自动转换,从小到到排序为:
byte < short/char < int < long < float < double
注意:任何浮点类型都比长整型还大;short
和char
虽然都是2个字节,但是char
可以取更大的正整数 - 大数转小数的时候需要使用强制转换符,并且在运行的时候可能会损失精度,需谨慎使用
- 当整数字面值没有超出
byte/short/char
取值范围时,可以直接赋值 byte/short/char
混合运算时,先各自转换成int
再运算- 多种类型运算时先转换成最大类型再运算
参考
B站动力节点老杜老师的Java教程(原视频戳这里)