数据类型(包含二进制讲解)
1 数据类型
1.1 数据类型有什么作用?
数据类型用来声明变量,程序在运行过程中根据不同的数据类型分配不同大小的空间。
int i = 10;
double d = 1.23;
i变量和d变量类型不同,空间大小不同。
1.2 数据类型在java语言中包括两种:
第一种:基本数据类型
基本数据类型又可以划分为4大类8小种:
第一类:整数型
第二类:浮点型
第三类:布尔型
第四类:字符型
8小种:
byte,short,int,long
float,double(只有小数的)
boolean:只有两个值 true false true表示真 false表示假
char:java中规定字符型字面量必须使用单引号括起来。属于文字。
第二种:引用数据类型
字符串型String属于引用数据类型。
String字符串不属于基本数据类型范畴。
java中除了基本数据类型之外,剩下的都是引用数据类型。
引用数据类型后期面向对象的时候才会接触。
1.3 8种基本数据类型中
整数型:byte short int long有什么区别?
浮点型:float和double有什么区别?
区别:占用的空间大小不同。
关于计算机存储单位?
计算机只能识别二进制。(100101000100110...)
1字节 = 8bit (8比特) --> 1byte = 8bit
1bit就是一个1或0.
1KB = 1024byte
1MB = 1024kb
1GB = 1024M
1TB = 1024G
byte b = 2;在计算机中是这样表示的 00000010
short b = 2;在计算机中是这样表示的 00000000 00000010
int i = 2;在计算机中是这样表示的 00000000 00000000 00000000 00000010
...
类型 占用字节数量(byte)
--------------------
byte 1
short 2
int 4
long 8
float 4
double 8
boolean 1
char 2
关于二进制?
二进制???
1 2 3 4 5 6 7
1 10 11 100 101 110 111...
十进制转换成二进制
125 转换成二进制???
办法:除以2,然后余数逆序输出。
1111101
二进制转换成十进制
2的2次方 2的1次方 2的0次方 --> 计算方法
1 1 1 --> 二进制
4 2 1 --> 计算结果
1*4 + 1*2 + 1*1 = 7 --> 计算结果
2的2次方 2的1次方 2的0次方 --> 计算方法
1 0 1 --> 二进制
4 2 1 --> 计算结果
1*4 + 0*2 + 1*1 = 5 --> 计算结果
1.4 byte类型的取值范围?
byte是[-128~127]共,可以标识256个不同的数字。
byte类型的最大值是怎么计算出来的?
byte是一个字节,是8个比特位,所以byte可以存储的最大值是:
01111111
注意:在计算机当中,一个二进制位最左边的是符号位,当为0时表示正数,
当为1时表示负数。所以byte类型最大值是:01111111
那么是不是2的7次方-1呢?
是不是:10000000(前边是一个二进制) - 1
byte类型最大值是:2的7次方 - 1
有几个取值范围需要大家记住:
(1个字节)byte: [-128 ~ 127]
(2个字节)short: [-32768 ~ 32767]
(4个字节)int: [-2147483648 ~ 2147483647]
(8个字节)char: [0 ~ 65535] 可以表示65536个不同的数字
问题?
char为什么也会有取值范围呢?
因为他即使是字符型,但是它的底层也是由二进制来实现的。
short和char实际上容量相同,不过char可以表示更大的数字。
因为char表示的是文字,文字没有正负之分,所以char可以表更大的数字。
1.5 对于8中基本数据类型来说:
其中byte,short,int,long,float,double.boolaen,这7种类型计算机表示起来比较容易,因为他们都是数字。
其中布尔类型只有两个值true和false,实际上true和false分别在c++中对应的是1和0,1为true,false为0。
对于char类型来说计算机表示起来比较麻烦,因为char对应的是文字,每一个国家的文字不一样,文字不能直接通过自然算法转换成二进制。
这个时候怎么办?
字符编码诞生了。
什么是字符编码?
字符编码是认为的定义的一套转换表。
在字符编码中 规定了一系列的文字对应的二进制。
字符编码其实本质上就是一本字典,该字典中描述了文字与二进制之间的对照关系。
字符编码是认为规定的。(是某个计算机协会规定的。)
字符编码涉及到编码和解码这两个过程,编码和解码的时候必须采用同一套字符编码方式,
不然就会出现乱码。
关于字符编码的发展过程?
起初的时候计算机是不支持文字的,只支持科学计算。实际上计算机起初是为了战争而开发的,计算导弹的轨道。。。
后来随着计算机的发展,计算机开始支持文字,最先支持的文字是英文,英文对应的字符编码方式:ASCII码。
ASCII码采用ibyte进行存储,因为英文字母是26个。(键盘上所有的键全部算上也超不过256个。1byte可以标识256种不同的情况。
所以英文本身在计算机方面就占有优势。)
'a' ---> 97(采用ASCII码进行编码) ---> 01100001
01100001 -- (采用ASCII码进行解码) -> 'a'
如果编码和解码采用的不是同一个编码方式,会出现乱码。
'b' ---> 98
'c' ---> 99
'A' ---> 65
'B' ---> 66
'0' ---> 48 (这个'0'不是那个0,是字符'0')
'1' ---> 49
随着计算机语言的发展,后来国际标准组织制定了 ISO-8859-1编码方式,
又称为latin-1编码方式,向上兼容ASCII码。但不支持中文。
后来发展到亚洲,才支持中文,日文,韩文...
中文这块的编码方式:GB2312<GBK<GB18030 (容量的关系)
以上编码方式是简体中文。
繁体中文:big5(台湾使用的是大五码。)
在java中,java语言为了支持全球所有的文字,采用了一种字符编码方式
叫做unicode编码。unicode编码统一了全球所有的文字,支持所有文字。
具体的实现包括:UTF-8 UTF-16 UTF-32......
需要记住:
ASCII
ISO-8859-1(latin-1)
GB2312
GBK
GB18030
Big5
unicode(utf8 utf16 utf32)
2 8种基本数据类型详解
字符型char
整数型byte short int long
浮点型 float double
布尔型 boolean
---------------------------------------------------------↓整数型↓----------------------------------------------------------
/* 字符型: 1 char占用2个字节。 2 char的取值范围:[0-65535] 3 char采用unicode编码方式 4 char类型的字面量使用单引号括起来 5 char可以存储一个汉字 */ public class CharTest01{ public static void main(String[] args){ // char可以存储1个汉字吗? // 可以的,汉字占用2个字节,Hjava中的char类型占用2个字节,正好 char c1 = 'a'; System.out.println(c1); char c2 = '0'; System.out.println(c2); char c3 = '中'; System.out.println(c3); //编译出错,不兼容的类型:String无法转换为char char c4 = "a"; //错误:未结束的字符文字 char c5 = 'c5'; } }
在jdk8中 输入native2ascii.exe点击回车
然后输入一些中文汉字,他会生成对应的unicode编码。
在java中就是采用unicode编码。
/* 在java中有一条非常重要的结论,必须记住: 在任何情况下,整数型的“字面量/数据”默认被当做int类型处理。(记住就行) 如何希望该“整数型字面量”被当做long类型来处理,需要在“字面量”后面添加L/l 建议使用大写L,因为小写1和l傻傻分不清 */ public class IntTest02{ public static void main(String[] args){ //分析这个代码类型存在类型转换吗,以下代码什么意思? //不存在类型转换 //100这个字面量被当做int类型处理 // a变量是int类型,所以不存在类型的转换 // int类型的的字面量赋值给int类型的变量。 int a = 100; System.out.println(a); // 分析这个程序是否存在类型转换? // 分析:200这个字面量默认被当做int类型来处理 // b变量是long类型,int类型占4个字节,long类型占8个字节 // 小容量可以自动转换成大容量,这种操作被称为:自动类型转换。 long b = 200; System.out.println(b); //分析这个是否存在类型转换? // 这个不存在类型转换。 // 在整数型字面量300后面添加一个L之后,300L联合起来就是一个long类型的字面量 //c变量是long类型,long类型赋值给long类型不存在类型转换。 long c = 300L; // 题目: // 可以吗?存在类型转换吗? // 2147483647默认被当做int来处理 // d变量是long类型,小容量可以自动赋值给大容量,自动类型转换 long d = 2147483647;// 2147483647是int最大值。 System.out.println(d); //编译器会报错吗?为什么? //字面量默认为int,你没有去转换数据类型(就是在后面加上类型的大写字母),那么当字面量超过int的最大范围。 //所以在没有赋值之前就出错了,那么就会报错,e是long类型,完全可以容纳21474836478 // 错误: 整数太大 //long d = 2147483648; //怎么解决这个问题呢? long e = 2147483648L; System.out.println(e); } }
/* 1 小容量可以直接赋值给大容量,成为自动类型转换 2 大容量不能直接赋值给小容量,需要需要强制类型转换符进行强转 但需要注意的是:加强制类型转换符之后,虽然编译通过了,但是运行的时候可能会损失精度。 */ public class IntTest03{ public static void main(String[] args){ // 不存在类型转换 // 100L是long类型字面量,x是long类型字面量。 long x = 100L; //这样可以吗?x是long类型,占用8个字节,而y变量是int类型,占用4个字节。 // 那么在java语言中,大容量可以“直接”赋值给小容量吗? // 编译错误信息:错误: 不兼容的类型: 从long转换到int可能会有损失 //int y = x; //大容量转换成小容量,想要编译通过,必须加强制类型转换符,进行强制类型转换。 //底层是怎么进行强制类型转换的呢? //long类型100L:00000000 00000000 00000000 00000000 00000000 00000000 00000000 01100100 // 以上的long类型100L强转int类型,会自动将“前面”的4个字节砍掉:00000000 00000000 00000000 01100100 int y = (int)x;//这个(int)就是强制类型转换符,加上去就能编译通过。 //但是要记住:编译虽然通过了,但是运行时可能损失精度。 System.out.println(y); //100 //定义变量a int类型,赋值100 int a = 100; System.out.println(a); int b = a;// 将变量a中保存的值复制一份给b变量 System.out.println(b); } }
/* java中有一个语法规则: 当这个整数型字面量没有超出byte的取值范围,那么这个整数型字面量可以直接赋值给byte类型的变量。 这种语法机制是为了方便写代码而定制的。 */ public class IntTest04{ public static void main(String[] args){ // 分析:以下代码可以编译通过吗? // 300被默认被当做int类型。 // b变量是byte类型 // 大容量转换成小容量,要想编译通过,必须使用强制类型转换符。 // 错误: 不兼容的类型: 从int转换到byte可能会有损失 //byte b = 300; //要想让以上的程序编译通过,必须加强制类型转换符 // 虽然编译通过了,但是可能会有精度损失 // 300这个int类型对应的二进制是什么:00000000 00000000 00000001 00101100 // byte 占用1个字节,砍掉前3个字节,结果是 00101100 (32 8 4) byte b = (byte)300; System.out.println(b); //44 // 编译能通过吗? // 1是int类型,默认被当做int类型来看。 // x是byte类型,1个字节,大容量无法直接转换成小容量。 // 按说是编译报错的。 byte x = 1; byte y = 127; System.out.println(x); //错误: 不兼容的类型: 从int转换到byte可能会有损失 //byte z = 128; //当整数型字面量没有超出short类型取值范围的时候,该字面量可以直接赋值给short类型的字面量。 short s = 1; short s1 = 32767; //short s2 = 32768; System.out.println(s); } }
/* 1 计算机在任何情况下都只能识别二进制 2 计算机在底层存储数据的时候,一律存储的是“二进制的补码形式” 计算机采用补码形式存储数据的原因是:补码形式效率最高。 3 什么是补码呢? 实际上是这样的,二进制有:原码 反码 补码 4 记住: 对于一个正数来说:二进制原码、反码、补码、是同一个,完全相同。 比如int i = 1; 对应的二进制原码: 00000000 00000000 00000000 00000001 对应的二进制反码: 00000000 00000000 00000000 00000001 对应的二进制补码: 00000000 00000000 00000000 00000001 对于一个负数来说,二进制原码、反码、补码是什么关系呢? byte i = -1; 对应的二进制原码: 00000001 对应的二进制反码(符号位不变,其他位取反):11111110 对应的二进制补码(反码+1):11111111 5 分析 byte b = (byte)150; 这个b是多少? int类型的4个字节的150的二进制码是什么? 00000000 00000000 00000000 10010110 将以上的int类型强制类型转为1个字节的byte,最终在计算机的二进制码是: 10010110 千万要注意:计算机永远存储的都是二进制补码形式。也就是说上面的 10010110 这个是二进制补码形式,你可以采用逆推的方式推算出这个二进制补码对应的原码是啥!!! 10010110 --> 二进制补码形式 10010110 --> 二进制反码形式 11101010 --> 二进制原码形式 */ public class IntTest05{ public static void main(String[] args){ //编译报错,因为150已经超过了byte取值范围,不能直接赋值,需要强转。 //byte b = 150; byte b = (byte)150; System.out.println(b);// -106 } }
/* 结论: byte char short 做混合运算的时候,各自先转换成int在做运算。 */ public class IntTest06{ public static void main(String[] args){ char c1 = 'a'; byte b = 1; // 注意: 这里的加号是负责求和的 System.out.println(c1 + b); //98 // 错误: 不兼容的类型: 从int转换到short可能会有损失 //short s = c1 + b; //编译器不知道这个加法最后的结果是多少,只知道是int类型。 //这样修改可以吗? //错误: 不兼容的类型: 从int转换到short可能会有损失 //short s = (short)c1 + b; short s = (short)(c1 + b); //short k = 98; //System.out.println(k); int a = 1; //错误:不兼容的类型: 从int转换到short可能会有损失 //short x = 1; 可以 short x = a; // 不可以,编译器只知道a是int类型,不知道a中存储的是哪个值。 System.out.println(x); } }
/* 结论: byte char short 做混合运算的时候,各自先转换成int在做运算。 */ public class IntTest06{ public static void main(String[] args){ char c1 = 'a'; byte b = 1; // 注意: 这里的加号是负责求和的 System.out.println(c1 + b); //98 // 错误: 不兼容的类型: 从int转换到short可能会有损失 //short s = c1 + b; //编译器不知道这个加法最后的结果是多少,只知道是int类型。 //这样修改可以吗? //错误: 不兼容的类型: 从int转换到short可能会有损失 //short s = (short)c1 + b; short s = (short)(c1 + b); //short k = 98; //System.out.println(k); int a = 1; //错误:不兼容的类型: 从int转换到short可能会有损失 //short x = 1; 可以 short x = a; // 不可以,编译器只知道a是int类型,不知道a中存储的是哪个值。 System.out.println(x); } } /* 结论:多种数据类型做混合运算的时候,最终的结果类型是“最大容量”对应的类型。 char + short + byte 这个除外。 因为char + short + byte 混合运算的时候,会各自先转换成int在做运算。 */ public class IntTest07{ public static void main(String[] args){ long a = 10L; char c = 'a'; short s = 100; int i = 30; //求和 System.out.println(a + c + s + i); //错误: 不兼容的类型: 从long转换到int可能会有损失 //计算结果是long类型 int x = (int)(a + c + s + i); System.out.println(x); //以下程序执行结果是? int temp = 10 / 3; // / 是除号 System.out.println(temp); //最终取整数 结果是3 // 在java中计算结果你不一定是精确地。 int temp2 = 1 / 2; System.out.println(temp2); // 0 } }
---------------------------------------------------------↓浮点型↓----------------------------------------------------------
/* 关于java语言中的浮点型数据 浮点型包括: float 4个字节 double 8个字节 float 是单精度 double 是双精度 double 更精确 比如说: 10.0 / 3 如果采用float来存储的话结果可能是 3.333333 10.0 / 3 如果采用double来存储的话结果可能是 3.33333333333 但是需要注意的是,如果用在银行方面或者说使用在财务方面,double 也是远远不够的,在java中提供了一种精度更高的类型,这种类型专门使用在财务软件方面:java.math.BigDecimal(不是基本数据类型, 属于引用数据类型。) float和double存储数据的时候都是存储的近似值 为什么? 因为现实世界中有这种无限循环的数据,例如:3.33333333333..... 数据实际上是无限循环,但是计算机的内存有限,用一个有限的资源表示无限的数据,只能存储近似值。 long类型占用8个字节。 float类型占用4个字节。 哪个容量大? 注意:任意一个浮点型都比整数型空间大。 float容量大于long容量。 java中规定,任何一个额浮点型数据默认被当做double来处理。 如果想让这个浮点型字面量被当做float类型来处理,那么请在字面量后面添加F/f 1.0 那么1.0默认被当做double类型处理 1.0F 这才是float类型。(1.0f) */ public class FloatTest01{ public static void main(String[] args){ //这个不存在类型转换 double pi = 3.1415926; System.out.println(pi); //这个可以吗? //错误: 不兼容的类型: 从double转换到float可能会有损失 //float f = 3.14; //怎么修改以上代码呢? //第一种方式:在字面量后面添加F/f //float f = 3.14f; // 第二种方式 // 强制类型转换,但可能损失精度。谨慎使用 float f = (float)3.14; //分析这个程序可以编译通过吗? //错误: 不兼容的类型: 从double转换到int可能会有损失 //原理:现将5转换成double类型,然后在做运算,结果是double // 大容量无法赋值给小容量,需要强转。 //int i = 10.0 / 5; //怎么修改 int i = (int)10.0 / 5; //System.out.println(i); //2 //这么修改可以吗?强转的时候只留下整数位 int i = (int)10.0 / 5; System.out.println(i); //2 } }
---------------------------------------------------------↓字符型↓----------------------------------------------------------
/* 字符型: 1 char占用2个字节。 2 char的取值范围:[0-65535] 3 char采用unicode编码方式 4 char类型的字面量使用单引号括起来 5 char可以存储一个汉字 */ public class CharTest01{ public static void main(String[] args){ // char可以存储1个汉字吗? // 可以的,汉字占用2个字节,Hjava中的char类型占用2个字节,正好 char c1 = 'a'; System.out.println(c1); char c2 = '0'; System.out.println(c2); char c3 = '中'; System.out.println(c3); //编译出错,不兼容的类型:String无法转换为char char c4 = "a"; //错误:未结束的字符文字 char c5 = 'c5'; } }
/* 关于java中的转义字符 java语言中"\"负责转义 \t 表示制表符tab */ public class CharTest02{ public static void main(String[] args){ //普通的't'字符 char c1 = 't'; System.out.println(c1); //char x = 'ab'; //根据之前所学,以下代码应该报错。 //经过测试以下代码 \t实际上是1个字符,不属于字符串 //两个字符合在一起表示一个字符,其中\t表示"制表符tab键" char c2 = '\t'; //相当于键盘上的tab键 System.out.println("abctdef");//abctdef // \的出现会将紧挨着的后面的字符进行转义。\碰到t表示tab键。 System.out.println("abc\tdef");//abc def /* System.out.print();//不换行输出 System.out.println();//换行 */ System.out.print("HelloWorld"); System.out.println("123abcdef"); System.out.println("abc"); char c3 = '\n';// \n换行符 System.out.println(c3); System.out.println("def"); // 假设现在想在控制台输出一个'字符怎么办? //错误:空字符文字 //System.out.println('''); // \' 表示一个普通不能在普通的单引号字符。(\'联合起来表示一个普通的') System.out.println('\''); //假设现在想在控制台输出一个 \ 字符怎么办? //System.out.println('\'); //错误:未结束的字符文字 //System.out.println('\'); // 在java中两个\\反斜杠代表了一个"普通的反斜杠字符" System.out.println('\\'); // 双引号括起来是字符串 System.out.println("test"); // 希望输出的结果是 "test" // 错误: 需要')' //System.out.println(""test""); System.out.println("“test”");//内部的双引号我用中文的行吗?可以 System.out.println(""); System.out.println("\""); System.out.println("\"test\""); //这个可以输出吗? //这个不需要专门进行转义。 //这个'在这里只是一个普通的字符,不具备特殊含义。 System.out.println("'"); // 这个是有问题的 // 以下都有问题 //System.out.println('''); //System.out.println("""); //4e2d是一个字符串 //错误: 未结束的字符文字 //char x = '4e2d'; //反斜杠u表示后面的是一个字符的unicode编码 //unicode编码是十六进制的。 char x = '\u4e2d'; System.out.println(x);// 输出为 中 /* 十六进制,满16位进1位: 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... 八进制: 0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20... */ } }
/* 1 整数是否能直接赋值给char 2 char x = 97; 这个java语句是允许的,并且输出的结果是英文字母a 经过这个测试得到两个结论 第一个结论:当一个整数赋值给char类型变量的时候会自动转换成char字符型 最终的结果是一个字符。 第二个结论:当一个整数没有超出byte short char的取值范围的时候 这个整数可以直接赋值给byte short char类型的变量 */ public class CharTest03{ public static void main(String[] args){ char c1 = 'a'; System.out.println(c1); // 这里会做类型转换吗? // 97是int类型(这是java中固定的,默认当做int处理) // c2是char类型 char c2 = 97;// System.out.println(c2); // 'a' //char类型取值范围:[0~65535] char c3 = 65535; System.out.println(c3);//实际上最终结果是一个“看不懂”的字符。 //错误: 不兼容的类型: 从int转换到char可能会有损失 //char c4 = 65536; //怎么解决以上问题? char c4 = (char)65536; System.out.println(c4); byte x = 1; short s = 1; char c= 1; } }
---------------------------------------------------------↓布尔型↓----------------------------------------------------------
/* 1 在java语言中boolean类型只有两个值,没有其他值: true和false 不像c或c++,c语言中1和0也可以表示布尔类型。 2 boolean类型在实际开发总使用在哪里呢? 使用在逻辑判断当中,通常放到条件的位置上(充当条件) */ public class BooleanTest01{ public static void main(String[] args){ // 错误: 不兼容的类型: int无法转换为boolean // boolean xingBie = 1; // 需求规定:如果为true则表示男,为false则表示女 //boolean sex = true; boolean sex = false; int a = 10; int b = 20; System.out.println(a < b); // true System.out.println(a > b); // false boolean flag = a < b; //运算符是有优先级的,不确定可以加小括号。加了小括号的就一定是先执行的。 System.out.println(flag); // 后面我们会学习if语句 // if语句是一个条件语句 // 可以实现什么功能呢?例如:如果A账户的钱充足,才可以向B账户转账。 // 例如:如果这个布尔型值位true,则表示男性,为false则表示女性。 if(sex){ System.out.println("男"); }else{ System.out.println("女"); } // 以上的if语句看不懂没关系。后面会学习。 } }
---------------------------------------------------------↓综合以上总结↓----------------------------------------------------------
综合详述:
1 关于数据类型详解:
整数型:byte short int long
浮点型:float double
布尔型:boolean
字符型:char // 没有超出char的取值范围可以直接赋值给char变量吗?
2 综合的看一下,在类型转换的时候,需要遵循那些规则?
第一条:八种基本数据类型中,除boolean类型不能转换,剩下七种类型之间都可以进行转换;
第二条:如果整数型字面量没有超出 byte short char 的取值范围,可以直接将其赋值给byte short char类型的变量
char c = 100;
byte b = 127;
short d = 111;
第三条:小容量向大容量转换成为自动类型转换,容量从小到大的排序为 byte < short(char) < int < long < float < double ,其中short和char都占用两个字节,
但是char可以表示更大的正整数
第四条:大容量转换成小容量,成为强制类型转换,编写时必须添加“强制类型转换符”,但运行时可能出现精度损失,谨慎使用。
第五条:byte short char类型混合运算时,先各自转换成int类型在做运算
第六条:多种数据类型混合运算,各自先转换成容量最大的那一种在做运算。
所有的笔试题都超不出以上的6条规则,死记硬背
byte 是怎么算出来的: