一、java的数据类型
java的数据类型分为两大类:
- 八大基本数据类型
- 整数类型
- byte 占1个字节:-128 ~ 127
- short 占2个字节:-32768 ~ 32767
- int (常用)占4个字节:-2147483648 ~ 2147483647(21亿)
- long 占8个字节:-9223372036854775808 ~ 9223372036854775807
- 浮点类型
- float 占4个字节
- double(常用)占8个字节
- 字符类型 char 占2个字节
- 布尔类型 只占1位
- 引用数据类型 (除了基本数据类型,剩下的就是引用类型)
- 类
- 接口
- 数组、
//八大基本数据类型
int num1 =10;
byte num2= 100;
short num3 =30;
long num4=30L; //不加L没法区分是其他类型还是long类型
float num5=5.12F;//加F,道理同上
double num6=1.234567898765431;
char c='你';
boolean flag=true;
主要注意这两个:
1. 整型拓展
//二进制0b 八进制0 十进制 十六进制0x
int num1 =0b1010; //=(1×2×2×2)+(0×2×2)+(1×2)+0=10
int num2 =0120; //=(1×8×8)+(2×8)+0=80
int num3 = 1234; //=(1×10×10×10)+ (2×10×10)+(3×10)+4=1234
int num4 = 0xfff; //(15×16×16)+(15×16)+15=4095
2.浮点型拓展
1)如下情况,在num1和num2都输出为0.1时,num1却不等于num2
float num1 = 0.1f; //0.1
double num2 = 1.0/10; //0.1
System.out.println(num1); //0.1
System.out.println(num2); //0.1
System.out.println(num1==num2); //flase
2)在num1和num2都输出为0.6时,num1却不等于num2
float num1 = 0.6f; //0.6
double num2 = 0.6; //0.6
System.out.println(num1); //0.6
System.out.println(num2); //0.6
System.out.println(num1==num2); //false
3)当num1和num2都输出为0.0625时,true
float num1 = 0.0625f;
double num2 = 0.0625;
System.out.println(num1); //0.0625
System.out.println(num2); //0.0625
System.out.println(num1==num2); //true
4)这种情况下却输出了true
float f1 = 212121212f;
double d1 = f1+1;
System.out.println(f1==d1); //true
究其原因,问题出在浮点数在计算机中的表示。我们以IEEE754标准的单精度浮点数格式为例,其表示方法如下:
你会发现,这种表示方式只能表示刚刚好由2^(-n)组合起来的数:
k1×2^(-1) + k2×2^(-2) + k3×2^(-3) + k4×2^(-4)+...kn×2^(-n) kn=0或1
所以,这样是没法表示十进制的0.1的。只有0.59375这种“刚刚好”的数,才能用0.10011B表示出来。0.59376或者0.6都是没法表示的。
也就是说,虽然我们的float和double能表示如下这么大范围的数,
离散的,中间有很多数都表示不了(比如0.1、0.6),只能以一个接近它的数去表示。
刚刚解释完了小数部分,那么对于例4)里的大数呢?怎么解释?
找一个接近但是不等于的数去表示它,所以也是离散的。
综上,我们得出一个结论,避免使用浮点数去进行数值比较。
那么对于小数或者大额数字如何精确表示呢?经典场景就是微信支付和支付宝(或者银行业务),钱可不能近似表示。
用BigDecimal这个数学工具类。
3. 字符拓展
1)Unicode编码
java默认采用Unicode编码而不是ASCII,每一个字符都对应一个int型数值。只需要记住,字符的本质是数值。
Unicode包含了ASCII。也就是说,无论用ASCII编码还是Unicode编码,A-Z都对应65-90.
char a ='a';
char b ='明';
System.out.println((int)a); //97
System.out.println(a); //a
System.out.println((int)b); //26126
System.out.println(b); //明
ASCII码只能表示英文,对于英美这样的国家足够了。Unicode编码占两个字节,最多可以表示65536个字符,对于汉语还是不够用(10万字左右)。Unicode只是一种概念编码,而UTF-8是其一种实现形式。
因为我们使用汉语,一般使用UTF-8,UTF-8是可变长的编码,对于汉字占3个字节,足够汉语的使用了。
二、数据类型转换
首先,将除布尔值以外的数据类型按照精度由低到高排列:
byte(1) -> short char(2) -> int(4) -> long(8) -> float (4) -> double(8)
自动类型转换:把级别低的类型赋值给级别高的类型时,自动完成类型转换
强制类型转换:反之,必须使用类型转换运算。此时可能导致①内存溢出、②精度的损失。
// 1.自动类型转换
int a =50;
double b = a;
System.out.println(a); //50
System.out.println(b); //50.0
// 2.强制类型转换
int c = 98;
System.out.println((char)c); //int->char的强制转换 //'b'
// 1) 内存溢出问题---->byte截断int的低8位
int d =128;
byte e = (byte)d;
System.out.println(e); //-128
int a = 128+256; // ...1_1000_0000
byte b =(byte)a;
System.out.println(b); //-128
// 2) 精度损失问题
double f=123456786.3215498754;
float ff=(float)f;
System.out.println(ff); //1.23456784E8
例1)
//JDK7的新特性,大数之间用下划线分割便于阅读
int money=10_0000_0000;
int year=20;
int total1=money*year; //200亿,int最大表示21亿
System.out.println(total1);
long total2=money*year;
System.out.println(total2);
long total3=money*((long)year);
System.out.println(total3);