【Java】数据类型
数据类型
Java是一种强类型语言。这就意味着必须为每一个变量声明一种类型。在Java中,一共有8种(primitive type)基本类型,其中有4种整型(byte、short、int、long)、2种浮点类型(float、double)、1种用于表示Unicode编码的字符单元的字符类型char和1种用于表示真值的boolean类型。
基本数据类型相关(8个):byte、short、int、long、float、double、char、boolean 。
8位整数类型、16位整数类型、32位整数类型、64位长整数类型、32位单精度浮点数类型、64位双精度浮点数类型、 布尔类型。
1 、Java数据类型的分类
1、基本数据类型
8种:整型系列(byte,short,int,long)、浮点型(float,double)、单字符型(char)、布尔型(boolean)。
byte(1个字节)short(2个字节)int(4个字节,整数的默认类型)long(8个字节)
字节byte:1个字节,-128~127
短整型short:2个字节,-32768~32767。
浮点型:float(4个字节)double(8个字节,小数的默认类型)。
字符型:char(2个字节)。
布尔型:boolean(只有两个值true和false)。
2、引用数据类型
类、接口、数组、枚举…
类(class)/接口(interface)eg:String字符串,数组([])。泛型(<>)。
基本数据类型:整型、浮点型、字符型、布尔型
引用数据类型: 类、接口、数组、枚举
2、 Java的基本数据类型
1、整型系列
(1)byte:字节类型
占内存:1个字节
存储范围:-128~127
(2)short:短整型类型
占内存:2个字节
存储范围:-32768~32767
(3)int:整型
占内存:4个字节
存储范围:-2的31次方 ~ 2的31次方-1
(4)long:整型
占内存:8个字节
存储范围:-2的63次方 ~ 2的63次方-1
注意:如果要表示某个常量数字它是long类型,那么需要在数字后面加L
2、浮点型系列(小数)
(1)float:单精度浮点型
占内存:4个字节
精度:科学记数法的小数点后6~7位
注意:如果要表示某个常量数字是float类型,那么需要在数字后面加F或f
(2)double:双精度浮点型
占内存:8个字节
精度:科学记数法的小数点后15~16位
3、单字符类型
char:字符类型
占内存:2个字节
Java中使用的字符集:Unicode编码集
字符的三种表示方式:
(1)‘一个字符’
例如:‘A’,‘0’,‘尚’
(2)转义字符
\n:换行
\r:回车
\t:Tab键
\\:\
\":”
\':
\b:删除键Backspace
(3)\u字符的Unicode编码值的十六进制型
例如:\u5c1a代表’尚’
4、布尔类型
boolean:只能存储true或false
5、注意
- Java的整型常量默认为 int 型,如果想要表示某个整数值是long型时,需要在值后面加L或l ,1与l分不清,一般是使用L来表示的 eg:
long a = 1L;
。java程序中变量常声明为int型,除非不足以表示大数,才使用long。经常使用int呀 整型数据。 - Java 的浮点型常量默认为double型,声明float型常量,须后加‘f’或‘F’ eg:
float f=3.14F;
。float可以保证十进制科学计数法小数点后6位有效精度和第7位的部分精度。double可以保证十进制科学计数法小数点后15位有效精度和第16位的部分精度。 - 字符型的值必须使用单引号,只能而且必须存储单个字符,不能是空单引号。例如:’a’、’\n’、’\u5c1a’。字符型使用Unicode编码(ASCII,特殊字符,中文、日文、韩文…)
- String是引用数据类型,String的常量值必须使用双引号。单独的双引号也是一个字符串值。eg:
String name="小蚂蚁";
3、了解 进制
计算机中任何的计算和存储都是以二进制方式实现的 0、1
位(bit) — 是计算机中最小的存储单位
字节(byte) — 计算机中基本的存储单元
1byte = 8bits、1KB = 1024Byte、1MB = 1024KB、1GB = 1024MB、1T = 1024GB
1、进制的分类:
(1)十进制
数字组成:0-9
进位规则:逢十进一
(2)二进制
数字组成:0-1
进位规则:逢二进一
(3)八进制
数字组成:0-7
进位规则:逢八进一
(4)十六进制
数字组成:0-9,af(或AF)
进位规则:逢十六进一
对于整数,有四种表示方式:
- 二进制:0,1 ,满2进1.以0b或0B开头(字母B大小写均可)。
- 十进制:0-9 ,满10进1.
- 八进制:0-7 ,满8进1.八进制数被冠以0来表示。
- 十六进制:0-9及A-F,满16进1,十六进制数被冠以0X来表示(字母X大小写均可)
如: 0x3f20(十六进制) 0732 (八进制)
2、请分别用四种类型的进制来表示10,并输出它的结果:(了解)
(1)十进制:正常表示
System.out.println(10);
(2)二进制:0b或0B开头
System.out.println(0B10);
(3)八进制:0开头
System.out.println(010);
(4)十六进制:0x或0X开头
System.out.println(0X10);
class Test01_JinZhi{
public static void main(String[] args){
System.out.println(10);//十进制,正常写
System.out.println(0B10);//二进制,在数字前面加0B或0b
System.out.println(0b10);//二进制,在数字前面加0B或0b
System.out.println(010);//八进制,在数字前面加0
System.out.println(0X10);//十六进制,在数字前面加0X或0x
System.out.println(0x0f);//15
}
}
3、为什么byte是-128~127?(理解)
1个字节:8位
0000 0001 ~ 0111 111 ==> 1~127
1000 0001 ~ 1111 1111 ==> -127 ~ -1
0000 0000 ==>0
1000 0000 ==> -128(特殊规定)
*解释:*计算机数据的存储(了解)
计算机数据的存储使用二进制补码形式存储,并且最高位是符号位,1是负数,0是正数。
规定:正数的补码与反码、原码一样,称为三码合一;
负数的补码与反码、原码不一样:
负数的原码:把十进制转为二进制,然后最高位设置为1
负数的反码:在原码的基础上,最高位不变,其余位取反(0变1,1变0)
负数的补码:反码+1
例如:byte类型(1个字节,8位)
25 ==> 原码 0001 1001 ==> 反码 0001 1001 -->补码 0001 1001
-25 ==>原码 1001 1001 ==> 反码1110 0110 ==>补码 1110 0111
底层是用加法代替减法:-128==》-127-1==》-127+(-1)
-127- -1 ==> -127 + 1
4、二进制与十进制之间的转换
二进制转成十进制 乘以2的幂数
十进制转成二进制 除以2取余数
5、二进制 八进制 十六进制互转
二进制转八进制:三位一组,算出这三位对应的十进制值,然后挨个连接上即可
二进制转十六进制:四位一组,算出这四位对应的十进制值,然后挨个连接上即可
八进制转二进制:把每个位置上的数字当做10进制的数,转成三位的二进制,然后挨个拼接上
十六进制转二进制:把每个位置上的数字当做10进制的数,转成四位的二进制,然后挨个拼接上
6、十进制与八进制或十进制与十六进制之间的转换,建议通过二进制过渡一下
7、原码、反码、补码
所有数字在计算机底层都以二进制形式存在。一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1。
Java整数常量默认是int类型,当用二进制定义整数时,其第32位是符号位;当是long类型时,二进制默认占64位,第64位是符号位。
因为机器数是带符号的,因此机器数与一个数的“二进制值”还是有区别的。
计算机以补码的形式保存所有的整数。
正数的原码、反码、补码都相同
负数的补码是其反码加1。
1.原码
原码即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:
+1 原码0000 0001
-1 原码1000 0001
2.反码
正数的反码是其本身
负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
+1 原码 0000 0001 反码 0000 0001
-1 原码 1000 0001 反码 1111 1110
3.补码
正数的补码就是其本身
负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
+1 原码 0000 0001 反码 0000 0001 补码 0000 0001
-1 原码 1000 0001 反码 1111 1110 补码 1111 1111
为什么要使用原码、反码、补码表示形式呢?
计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了.
0000 0000:0
0000 0001 ~ 0111 1111 : 1~ 127
1000 0001 ~ 1111 1111 : -127 ~ -1
1000 0000:-128
(-127) - (1) = -128
(1000 0001 - (0000 0001)= (1000 0000)
特殊值: -1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000]补 就应该是-128.
但是此时-128,如果用补码到反码,再到原码去计算是不对的,所以**-128是个特殊值,记住它**
8、疑惑解答?
(1)为什么float(4个字节)比long(8个字节)的存储范围大?
(2)为什么double(8个字节)比float(4个字节)精度范围大?
因为float、double底层也是二进制,先把小数转为二进制,然后把二进制表示为科学记数法,然后只保存:
(1)符号位(2)指数位(3)尾数位 网上搜索float型和double型数据的存储方式吧
4、 基本数据类型的转换
1、自动类型转换(自动升级):小容量转为大容量(系统自动完成)
-
byte,short,char三者之间不进行运算,若运算都将自动升级为int再做运算
-
boolean不与其他任意数据类型转换
-
任何数据类型与String之间使用“+”运算符都将自动“连接”成String类型
拼接
(1)当把存储范围小的值(常量值、变量的值、表达式计算的结果值)赋值给了存储范围大的变量时,
byte->short->int->long->float->double
char->
int i = 'A';//char自动升级为int
double d = 10;//int自动升级为double
(2)当存储范围小的数据类型与存储范围大的数据类型一起混合运算时,会按照其中最大的类型运算
int i = 1;
byte b = 1;
double d = 1.0;
double sum = i + b + d;//混合运算,升级为double
(3)当byte,short,char数据类型进行算术运算时,按照int类型处理
byte b1 = 1;
byte b2 = 2;
byte b3 = (byte)(b1 + b2);//b1 + b2自动升级为int
char c1 = '0';
char c2 = 'A';
System.out.println(c1 + c2);//113 48
(4)boolean类型不参与
2、强制类型转换
大容量转小容量,需要使用强制符(),结果可能损失精度或溢出
(1)当把存储范围大的值(常量值、变量的值、表达式计算的结果值)赋值给了存储范围小的变量时,需要强制类型转换
double->float->long->int->short->byte
->char
提示:有风险,可能会损失精度或溢出
double d = 1.2;
int num = (int)d;//损失精度
int i = 200;
byte b = (byte)i;//溢出
(2)boolean类型不参与
(3)当某个值想要提升数据类型时,也可以使用强制类型转换
int i = 1;
int j = 2;
double shang = (double)i/j;
提示:这个情况的强制类型转换是没有风险的。
byte,short,char之间是互不转换的,包括byte+byte等运算也会变成int
boolean和谁都不转
String类型的数据与任意类型的数据“+”拼接后结果都是String字符串
5、 特殊的数据类型转换
1、任意数据类型的数据与String类型进行“+”运算时,结果一定是String类型
System.out.println("" + 1 + 2);//12
2、但是String类型不能通过强制类型()转换,转为其他的类型
String str = "123";
int num = (int)str;//错误的
6、code
基本数据类型
/*
Java强类型 非常非常重要
Java中的数据类型:
(1)基本数据类型(8种)
(2)引用数据类型
String是引用数据类型
一、基本数据类型
1、整型系列
byte: 字节类型 范围:-128~127
1个字节 8个位
short:短整型
2个字节 范围:-32768~32767
int:整型
4个字节 范围:....
long:长整型
8个字节
说明:对于long类型的常量,需要加大写L(建议用大写)或小写l
2、小数类型,浮点型系列
float:
单精度浮点型,4个字节,
大概的精度范围是,把小数用科学记数法表示后,小数点后6~7位
说明:float类型的常量,需要在数字后面加F或f
double:双精度浮点型,8个字节
大概的精度范围是,把小数用科学记数法表示后,小数点后15~16位
L , F ,
3、字符类型
char:单字符类型,2个字节,可以表示汉字
在Java中是使用Unicode编码表表示。(兼容ASCII码)
每一个字符都有一个唯一的Unicode编码值。
例如:
数字0,Unicode编码值是48
数字1,Unicode编码值是49
...
字母A,Unicode编码值是65
字母B,Unicode编码值是66
...
字母a,Unicode编码值是97
字母b,Unicode编码值是98
...
如何表示char类型的字符常量呢?
(1)'一个字符',例如:'女','A'
(2)'转义字符',例如:'\n'(换行),'\t'(制表位Tab键),
'\\'(斜杠),'\"'(双引号),'\''(单引号),
'\b'(删除键Backspace),'\r'(回车键)
(3)'斜杠u字符的Unicode编码值的十六进制形式'
4、布尔类型
boolean:只能存两个值之一:true,false
一般boolean的值用于条件判断
计算机表示数据用二进制表示,即0和1
那么一位0或1,我们用bit(位),最小单位
计算机中最基本的单位用的byte字节,
1字节 = 8位
1KB = 1024B
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
...
扩展:
硬件厂商存储单位用1000进位,不是1024.
带宽 100Mb,b = bit
100M 12.5MB/s Mb/s ???
*/
class TestType{
public static void main(String[] args){
boolean marry = false;
if(marry){//marry中的值为true,就表示条件成立
System.out.println("已婚");
}else{
System.out.println("未婚");
}
System.out.println("--------------------------");
byte b = 127;
// byte b = 129; //不兼容的类型 从int转换到byte可能会有损sun失
long tel = 18201583096L;
float f = 1.2F;
char shuang = '"';//这样可以,表示单个字符
System.out.println(shuang);
System.out.println("渐若窥宏大说:\"今天天气真好\"");//这里要输出双引号,需要转义
char shang = '\u5c1a';
System.out.println(shang);
}
}
进制
/*
进制:(了解)
Java
十六进制 0x0f 0X0f 表示十进制15
八进制 017 15
二进制 0b1111 0B1111
1、进制的分类
十进制:
数字范围:0-9
进位规则:逢十进一
二进制:
数字范围:0-1
进位规则:逢二进一
八进制:
数字范围:0-7
进位规则:逢八进一
十六进制:
数字范围:0-9、A-F(或者a-f)
进位规则:逢十六进一
8对7说我溢出了 16对15我要进位了 2对1说嗯嗯
2 8 16 10
十进制 二进制 八进制 十六进制
0 0 0 0 0
1 1 1 1 1
2 2 10 2 2
3 3 11 3 3
4 4 100 4 4
5 5 101 5 5
6 6 110 6 6
7 7 111 7 7
8 8 1000 10 8
9 9 1001 11 9
10 10 1010 12 A
11 11 1011 13 B
12 12 1100 14 C
13 13 1101 15 D
14 14 1110 16 E
15 15 1111 17 F
16 16 10000 20 10
。。。。
25 25 11001
本质上,就是生活中的十进制,和计算机世界中的二进制
因为在计算机中二进制数字太长了,在代码中去表示二进制很繁琐,
那么引入了八进制和十六进制,为了快速和简短的表示二进制
为了快速和简短的表示二进制
(1)十进制-->二进制
(2)二进制-->八进制
把二进制从最右边开始,三位一组
(3)二进制-->十六进制
把二进制从最右边开始,四位一组
2、在程序中如何表示某个数字是十进制、二进制、八进制、十六进制
十进制,正常写
二进制,在数字前面加0B或0b
八进制,在数字前面加0
十六进制,在数字前面加0X或0x
3、为什么byte类型的范围是-128~127?
byte是1个字节,1个字节是8位
计算机中是使用“补码”的形式来存储数据的,为了理解/换算“补码”,我们在引入“原码、反码”。
规定:正数的原码、反码、补码三码合一;
负数的原码、反码、补码是不同的。
因为计算机中把最高位(最左边的二进制位)定为符号位,0表示正数,1表示负数。
正数的原码、反码、补码三码合一
负数的原码、反码、补码是不同的
25:
原码:0001 1001
反码:0001 1001
补码:0001 1001
-25:
原码:1001 1001
反码:1110 0110 符号位不变,其余位取反(0变1,1变0)
补码:1110 0111 在反码上加1
符号位 0 正数 1 负数
负数 反码 补码 - 1
正0: 0000 0000
正数:
0000 0001 : 1
|
0111 1111 : 127
2^7-1 = 127
负数:补码
1000 0001 : 补码(1000 0001)-》反码(1000 0000)--》原码(1111 1111) -127
|
1111 1111 : 补码(1111 1111)-》反码(1111 1110)--》原码(1000 0001)-1
负0:1000 0000 如果用它表示负0,就浪费了,所以用它来表示其他的数
-127的二进制的补码:1000 0001
1的二进制的补码:0000 0001
1000 0000 -128
计算机中用符号位来表示正、负
-127 - 1 = (补码:1000 0001)-(补码:0000 0001) = 补码(1000 0000) = -128
计算机中用符号位来表示正、负,就是为了底层设计的简化,让符号位也参与计算。
*/
class Test01_JinZhi{
public static void main(String[] args){
System.out.println(10);//十进制,正常写
System.out.println(0B10);//二进制,在数字前面加0B或0b
System.out.println(0b10);//二进制,在数字前面加0B或0b
System.out.println(010);//八进制,在数字前面加0
System.out.println(0X10);//十六进制,在数字前面加0X或0x
System.out.println(0x0f);//15
}
}
float和double在底层如何存储?
/*
了解:浮点型的float和double在底层如何存储?
计算机中只有二进制?
那么如果存储3.14?
小数涉及:(1)整数部分(2)小数部分(3)这个.(4)正负号
如何底层存储呢
计算机中只有二进制?
那么如何存储3.14呢?
化繁为简:
1、小数-->二进制:
(1)整数部分:除2倒取余
(2)小数部分:乘2取整数部分
小数 二进制
整数部分 除2倒取余
3.14==》11.00100...
截取
2、把这个二进制用科学记数法表示
1.1 00100.... * n的1次方
用科学计数法表示后,对于二进制的科学计数法,整数部分永远是1,那这样的话,
整数部分就不用存了,小数点也不存了
移动 移位 整数部分永远是1 小数点也不需要存储了
只要存三个内容:(1)正负号(2)挪完后的几次方,指数(3)二进制的小数部分(称为尾数)
float:4个字节,就被分为三个部分,最高位还是符号位,
接下来的8位用来存指数部分,然后剩下的存尾数,额如果存不下的尾数,就舍去了
1 8 23
double:8个字节,就被分为三个部分,最高位还是符号位,
接下来的11位用来存指数部分,然后剩下的存尾数,额如果存不下的尾数,就舍去了
1 11 52
了解:
(1)浮点类型不精确,因为十进制的小数部分转二进制会需要舍去
(2)float类型的4个字节能表示的数字范围比long类型的8个字节还要大
因为浮点型底层存的是指数
*/
public class Test02_FloatDoubleSave{
}
基本类型转换
/*
基本数据类型之间的转换:
(1)自动类型转换
①把存储范围小的类型的值赋值给存储范围大的类型的变量,自动可以完成升级
byte->short->int->long->float->double
char->
②boolean不参与
③byte,short,char如果进行算术运算都会自动升级为int
(2)强制类型转换
①把存储范围大的类型的值,赋值给存储范围小的类型变量时,需要强制类型转换
double->float->long->int->short->byte
->char
大的给小的 溢出 sun损失精度
强制类型转换是有风险的:可能会溢出或损失精度
②boolean不参与
③当需要把某个存储范围小的变量强制提升为存储范围大的类型时,也可以使用强制类型转换
*/
class Test03_TypeChange{
public static void main(String[] args){
/*
从左边看d1是double类型
从右边看10是int类型
int类型的值,赋值给了double类型的变量,那么它会自动升级为double
*/
double d1 = 10;
System.out.println("d1 = " + d1);//d1 = 10.0
/*
从左边看i1是int类型
从右边看10.0是double类型
double类型的值,赋值给int类型的变量,如果直接赋值会报错:错误: 不兼容的类型: 从double转换到int可能会有损失
*/
//int i1 = 10.3;
int i1 = (int)10.3;
System.out.println("i1 = " + i1);//i1 = 10
byte b1 = 127;
byte b2 = 2;
//byte b3 = b1 + b2;//报错:不兼容的类型: 从int转换到byte可能会有损失,因为byte+byte就自动升级为int
byte b3 = (byte)(b1 + b2);
// 0111 1111 0000 0010 1
// 1000 0001
// 反码 1000 0000 原码 1111 1111 -127
System.out.println("b3 = " + b3);//b3 = -127
short s1 = 1;
short s2 = 2;
//short s3 = s1 + s2;//short+short会自动升级为int
short s3 = (short)(s1 + s2);
System.out.println("s3 = " + s3);//s3 = 3
char c1 = '0';//'0'的编码值是48
char c2 = '1';//'1'的编码值是49
//char c3 = c1 + c2;//char+char会自动升级为int
char c3 = (char)(c1 + c2);
System.out.println("c3 = " + c3);//'a' 97
//c3 = a
boolean flag = true;
//int num = (int)flag;//不兼容的类型: boolean无法转换为int
int x = 1;
int y = 2;
System.out.println("x / y = " + x/y);//整数/整数,结果还是整数,只保留整数部分
System.out.println("x / y = " + (double)x/y);//把x的int类型先强制升级为double类型
}
}
/*
数据类型转换的特例:字符串类型
所有类型与字符串“+”拼接,结果都是字符串
*/
class Test04_TypeChange{
public static void main(String[] args){
char c1 = '0';
char c2 = '1';
/*
c1 + c2,按照求和运算,char + char结果是int
""代表空字符串,
当int的97与""进行 “+”拼接,结果还是97的字符串
*/
System.out.println(c1 + c2 + "");//97
// '0' + '1' int + "" 48 + 49 97
/*
"" + c1,按照“拼接”运算,字符串 + char,结果是字符串,结果是"0"
"0" + c2,按照“拼接”运算,字符串 + char,结果是字符串,结果是"01"
*/
System.out.println("" + c1 + c2 );//01
/*
c1 + "",按照“拼接”运算,char + 字符串 ,结果是字符串,结果是"0"
"0" + c2,按照“拼接”运算,字符串 + char,结果是字符串,结果是"01"
*/
System.out.println(c1 + "" + c2 );//01
}
}