由于Java是一种强类型语言,声明一个变量必须规定数据类型(基本数据类型、引用数据类型)基本数据类型的分类(四类八种)
- 整数型
- byte
- short
- int
- long
- 浮点型
- float
- double
- 布尔型
- boolean
- 字符型
- char
| 占用字节 | 范围 | |
|---|---|---|
| byte 字节 | 1 | -128~127 |
| short 短整型 | 2 | -2^15 - 2^15-1 |
| int 整型 | 4 | -2^31~ 2^31-1 |
| long 长整型 | 8 | -2^63~ 2^63-1 |
2:要想表示更大范围的整数,可以使用BigInteger、BigDecimal
3:整型默认为int型
4:声明long型,需要在数字后面加L或者l
5:bit是计算机中最小的存储单位。byte是计算机中基本的存储单位。1 byte = 8 bit
6:int a = 1L;//编译出错,long类型不能转为int类型
long b = 1;//编译通过
7:byte b = 1;//编译通过,没出出现向下转型的编译问题是因为:编译器会自动检查,数字是否超出范围,是否会造成精度丢失,
如果不会造成精度丢失,会自动进行类型转换。
byte b1 = 127;//编译通过,没有超出范围会自动强制转型
byte b1 = 128;//编译不通过,因为超出范围
8:int a = 1;
byte b = a; //编译失败,a是int类型,在内存中是按4字节存储空间,因此4字节空间不能存入byte范围
因此,如果是按变量赋值,直接判断类型范围。
9:short s1 = 1;
s1 = s1 + 1; // 编译不通过,错误,s1+1 是int 类型,需要强转才能赋值给s1;
s1 += 1; // 可以编译通过。s1 += 相当于 s1 = (short)(s1+1),其中有隐含的强转,对于 += 是Java 提供的运算符,编译器会对它进行转换处理
为什么byte的范围是-128~127?
计算机中运算时是以补码的方式运算的,二进制的最左侧为最高位,0表示正数,1表示负数 正数的最大二进制是01111111,正数的补码还是本身,因此正数的补码是: 0*2^8 + 1*2^7 + 1*2^6 + 1*2^5 + 1*2^4 + 1*2^3 + 1*2^2 + 1*2^1 = 127 负数最小的二进制原码是10000000,负数的补码=反码+1, 负数的反码=(原码符号位不变,其余位数取反)。最小的二进制负数补码是(原码10000000-> 反码11111111->补码-(127+1) = -128) 总结:二进制8位最大值是01111111转换为10进制是127 二进制8位的最小值10000000转换位10进制是-128,因此byte的取值范围是-128-127浮点型
| 占用字节 | 范围 | |
|---|---|---|
| float 单精度 | 4 | |
| double 双精度 | 8 |
1:浮点型默认是double类型 2:声明float型,必须加上f或者F 3:folat f = 1.1;//编译失败,1.1默认是double类型 4:double d = 1.1f;//编译通过,1.1f是float型 5:double的精度高于float,保留的小数点的位数也更多 6:0.1*3 == 0.3 //false 0.1*2 == 0.2 //true 7:为什么说 double 是双精度,float 是单精度呢? float 有效位数是 6 ~ 7位,double 有效位数是 15 位,有效位数的意思是:小数点后有几位。 double 的数值精度是 float 的 2 倍,因此,double 是双精度,float 是单精度。
浮点型数据存放形式:符号位+指数位+尾号位
sign:符号位,用来表示正负数,0表示正数,1表示负数
exponent:指数位,用来表示指数,实际要加上偏移量
fraction:小数位,用来表示小数,不足位数补0
从这里看出,指数位决定了大小范围,小数位决定了计算精度。当十进制转化为二进制后,得到的尾数位数有可能很长甚至无限长。所以当浮点格式存储数字时,实际存储的尾数是被截取或执行舍入后的近似值,这就解释了浮点数计算不准确的问题,因为近似值和原值是有差异的。
解决方式:
1)
double d1 = 1 - 0.9; // 0.09999999999999998 double d2 = 0.1; d1 == d2 ;// false 对于运算后的小数之间比较,使用Math.abs(d1-d2) == 0 ;// 判断是否相等
2)使用BigDecimal.compareTo
拓展银行业务的钱方面数据为什么不能使用浮点数表示?
float f1 = 322343545657f;
float f2 = f1 + 1;
System.out.println(f1 == f2);
float d1 = 0.1f;
double d2 = 0.1d;
System.out.println(d1 == d2);
double d3 = 1-0.9;
double d4 = 0.1;
System.out.println(d3 == d4);
double d33 = 0.1;
double d44 = 0.1;
System.out.println(d33 == d44);
原因是:float或者double都是有限的离散数据,有舍入误差。可以使用Bigdecimal来做比较或者运算
字符型
| 占用字节 | 范围 | |
|---|---|---|
| char 字符 | 2 | 0 - 65535 |
1:char可以数字、字母、汉字、制表位 2:将一个数字赋值给char型,当输出这个变量值时,会输出数字代表的unicode码对应的字符。 3:char c = 97;//a char c1 = 'a';//默认输出是unicode码对应的字符,那么应该(int)c1 = 97 4:int a = 'a' + 10; //编译器会先将'a'转为97 5:char c = 'a' + 10; System.out.print((int)c);//97+10 System.out.print(c);//107对应的unicode码 6:字符型存储到计算机中的过程:将字符对应的整数找出来,然后转化为二进制存储到计算机 读取的过程:将数字取出,转化为unicode对应的编码显示 7:字符编码: ASCII编码是对英语字符和二进制之间的关系做了统一规定,每一个字符使用1个字节表示的, 使用字节中的低7位表示,最前面一位表示为0,一共有128个字符, 实际上一个字节可以表示256个字符。但是不能表示中文 Unicode固定大小的编码编码使用2个字节表示字符,字母和汉字都占2个字节,不会出现乱码问题 Unicode码兼容Ascii码 Utf-8大小可变的编码字母使用一个字节,汉字使用3个字节,UTF-8码是对Unicode码的改进,可变编码 gbk字母1字节,汉字2字节 gb2312也可以表示汉字(gb2312boolean
占用字节 范围 boolean 1 true或者false 1:只允许取true或者false,无null 2:boolean的默认值是false基本数据类型自动转换1:有多种数据类型混合运算的时候,系统会自动将数据类型都转化为容量最大的那个 int a = 1; float f = a + 1.1; //编译异常,因为a+1.1结果是double类型 float f = a + 1.1f;//正确 double d = a + 1.1;//正确 int a = 1.1;//编译失败 2:byte、short分别不能和char进行自动转换。 byte b = 1; char c = b; // 编译错误 byte b = 'a';//可以直接把char类型的字符赋值给byte,但是不能直接赋值变量 3:byte、short、char三者之间可以进行运算,不管是单独结算还是混合运算,会先自动转为int byte b = 1; short s = 2; short a = b+s;//编译错误,b+s结果是int类型 int a = b+s;//正确 byte b2 = 2; byte b3 = b+b2;//编译错误,b+b2结果是int类型 4: 为什么long占8字节,取值范围反而比4字节的float小? 因为浮点数和整数在内存中的存储机制不同,浮点数是符号位+指数位+小数位组成基本数据类型强制转换1:强制转换是自动转换的逆过程。将容量大的数据类型转换为容量小的数据类型, 使用时要加上强制转换符()。但可能会造成精度丢失 2:int a = (int)1.9;//1 造成了精度丢失 byte b = (byte)2000;// 造成了溢出 3:byte b = 1; b = b +1; //错误,int->byte b = (byte)(b+1);//正确。 4:byte b = 1; short s = 2; short s = s + b; 5:double d = 1/2; // 0.0,1/2由于都是int类型,0.5转int是0,0转化为double = 0.0 double d = 1/2d;//0.5 +1; //错误,int->byte b = (byte)(b+1);//正确。 4:byte b = 1; short s = 2; short s = s + b;基本数据类型和引用数据类型的区别 在内存中存储的位置不同基本数据类型存储于栈中,引用数据类型存储于堆中,栈中存储的是它的地址
传递方式不同
基本数据类型在调用方法时,是按照值传递的
//基本数据类型作为方法参数被调用 public class Main{ public static void main(String[] args){ int msg = 100; System.out.println("调用方法前msg的值:n"+ msg); //100 fun(msg); System.out.println("调用方法后msg的值:n"+ msg); //100 } public static void fun(int temp){ temp = 0; } }
引用数据类型是引用传递//引用数据类型作为方法参数被调用 class Book{ String name; double price; public Book(String name,double price){ this.name = name; this.price = price; } public void getInfo(){ System.out.println("图书名称:"+ name + ",价格:" + price); } public void setPrice(double price){ this.price = price; } } public class Main{ public static void main(String[] args){ Book book = new Book("Java开发指南",66.6); book.getInfo(); //图书名称:Java开发指南,价格:66.6 fun(book); book.getInfo(); //图书名称:Java开发指南,价格:99.9 } public static void fun(Book temp){ temp.setPrice(99.9); } }



