基本类型的两条准则:html
所占的字节数:java
byte: 1个字节; char: 2个字节; short: 2个字节; int: 4个字节; long: 8个字节; float: 4个字节;(6位小数,指数是:10^-38~10^38; 范围:) double: 8个字节;算法
char:Java中用 "\u四位十六进制的数字 (即便在注释中出现\u,后面若是 跟的不是4个16进制的数字,也会报错)"表示将字符转换成对应的unicode编 码;也能够用字符来赋值如: char c="\u0000" ,char的默认初始化值,unicode的null字符bash
基本类型的后缀:微信
long : l 或 L float: f 或 F; double: d 或 Dui
正如前面所说的,类型由大到小,是必需强制转换。但这并不意味着须要用户手动强制转换 —— 也就是 隐式转换。隐式转换 说的透彻点就是由编译器来进行强制转换,不须要用户再去写强制转换的代码。下面的前两个小点所说的即是特殊的隐式类型转换。spa
本小节所讨论的类型转换是不包括 类型由小到大的转换,讨论的是其余比较容易让人迷惑的类型转换设计
所谓的字面常量就是值的自己,如 五、七、“aa”等等。咱们先看个例子:code
public static void main(String[] args) {
int a = 8; //8是字面常量
byte b = 9; //9是字面常量
char c = 9+5;//常量表达式
short s = (short) (c+10); //变量表达式,须要显式强制转换
}
复制代码
上面的代码是通过编译的,是正确的。b是byte类型,但b=9不须要显式地手动强制转换,这是由于9是字面常量,是由JVM自动完成。 咱们再来看一下c=9+5
,c是char类型,9+5获得结果是int类型,但也不须要显式地手动强制转换。这是由于 9+5是常量表达式,因此在编译期间已经由编译器计算出结果了,即通过编译后,至关于 c=14,也是字面常量,因此能够隐式转换。同理,short s = (short) (c+10);
子因此不能隐式转换,就是由于表达式不是常量表达式,包含了变量,只能在运行期间完成,因此就要手动强制转换。htm
整形字面常量隐式转换的限制:
byte b = 128;//编译错误,128超出byte类型所能表示的范围
byte c = (byte)128;//编译经过
复制代码
编译器子因此这样要求,其实为了不 方法重载出现的隐式转换 与 小类型自动转大类型 发生冲突。
public static void main(String[] args) {
shortMethod(8);//编译错误
shortMethod((short)8); //编译经过
longMethod(8);//编译经过,由于这是小类型变成大类型,是不须要强制类型转换的
}
public static void shortMethod(short c){
System.out.println(c);
}
public static void longMethod(short l){
System.out.println(l);
}
复制代码
复合运算符(+=、-=、*=、/=、%=)是能够将右边表达式的类型自动强制转换成左边的类型
public static void main(String[] args) {
int a = 8;
short s = 5;
s += a;
s += a+5;
}
复制代码
s+=a、s+=a+5
;的表达式计算结果都是int类型,但都不须要手动强制转换。其实,若是是反编译这段代码的class文件,你会发现s+=a;,实际上是被编译器处理成了
s=(short)(s+a)
复制代码
也就是说对于全部的复合运算的隐式类型转换,实际上是编译器自动添加类型转换的代码。
因此,相对于整形字面常量的隐式转换,复合运算符的隐式转换则没有任何限制由于前者只能在编译器期间发生,后者则是编译器实实在在的补全了类型转换的代码。
char类型在基本类中是一个比较特殊的存在。这种特殊性在于char类型是一个无符号类型,因此char类型与其余基本类型不是子集与父集间的关系(其余类型都是有符号的类型)。也就是说,char类型与byte、short之间的转换都须要显式的强制类型转换(小类型自动转换成大类型失败)。
同时,因为char类型是一个无符号类型,因此对于整形字面常量的隐式转换的限制,不只包括字面常量数值的大小不能超出2个字节,还包括字面常量数值不能为负数
byte b = 2;
char c = 2;//编译经过
c = 100000000000;//编译不经过,超出char类型的范围
char d = -2//字面常量为负数,编译不经过
d = (char)-100;//编译经过
char f = (char)b; //编译经过,必须显式的强制类型转换
f = b;//编译不经过,不能隐式转换
int i = c;//编译经过,能够不须要强制类型转换
short s = (short) c;//编译经过,必须显式地强制类型转换
复制代码
char类型是无符号的类型,这种无符号也体如今在其转换成int类型时,也就是说,char类型在扩展时,也是按无符号的方式扩展,扩展位填0。咱们来看一个例子:
public static void main(String[] args) {
short s = -5;
char c = (char)s;
System.out.println(c==s); //false
System.out.println("(int)c = "+(int)c); //转换成int类型,值为65531
System.out.println("(short)c = "+(short)c); //-5
System.out.println("(int)s = "+(int)s);//-5
}
复制代码
运行结果:
false (int)c = 65531 (short)c = -5 (int)s = -5
从上面的结果发现,char类型的c 与 short类s其实存储字节码内容是同样的,但因为前者是无符号,因此扩展成int类型的结果是 65531,而不是 -5。运算符==比较的就是他们扩展成int类型的值,因此为fasle。
对char类型的类型转换,能够总结成如下几点:
在Java中,一个运算结果的类型是与表达式中类型最高的相等,如:
char cc = 5;
float dd = 0.6f+cc;//最高类型是float,运算结果是float
float ee = (float) (0.6d+cc);//最高类型是double,运算结果也是double
int aa = 5+cc;//最高类型是int,运算结果也为int
复制代码
可是,对于最高类型是byte、short、char的运算来讲,则运行结果却不是最高类型,而是int类型。看下面的例子,c、d运算的最高类型都是char,但运算结果倒是int,因此须要强制类型转换。
byte b = 2;
char a = 5;
char c = (char) (a+b);//byte+char,运算结果的类型为int,须要强制类型转换
int e = a+b;//编译经过,不须要强制类型转换,能够证实是int
char d = (char) (a+c);//char+char,
short s1 = 5;
short s2 = 6;
short s3 =(short)s1+s2;
复制代码
综上所述,java的运算结果的类型有两个性质:
咱们都知道,long类型转换成float类型是不须要强制类型转换的,也就是说相对于flaot类型,long类型是小类型,存储的范围要更小。然而flaot只占了4个字节,而long却占了8个字节,long类型的存储空间要比float类型大。这到底是怎么一回事,咱们接下来将细细分析。
浮点数使用 IEEE(电气和电子工程师协会)格式。 浮点数类型使用 符号位、指数、有效位数(尾数)来表示。要注意一下,尾数的最高
在java中,float 和 double 的结构以下:
|类 型|符 号 位|指 数 域|有效位域| |-|-|-| |float|1位|8位|23位| |double|1位 |11位|52位|
符号位: 0为正,1为负; 指数域: 无符号的,float的偏移量为127(即float的指数范围是-126~127,),double 有效位域: 无符号的;
1)存储的小数的数值多是模糊值
public static void main(String[] args) {
double d1 = 0.1;
double d2 = 0.2;
System.out.println(d1+d2 == 0.3);
System.out.println(d1+d2);
}
复制代码
运行结果:
false 0.30000000000000004
上述的运算结果并非错误。这是由于没法用二进制来准确地存储的0.3,这是一个无限循环的值,与10进制的1/3很类似。不仅是0.3,不少小数都是没法准确地用浮点型表示,其实这是由 小数的十进制转成二进制的算法所决定的,十进制的小数要不断乘2,知道最后的结果为整数才是最后的二进制值,但这有可能怎么也得不到整数,因此最后获得的结果多是一个 无限值 ,浮点型就没法表示了
可是对于 整数 来讲,在浮点数的有效范围内,则都是精确的。一样,也是因为转换算法:十进制的整数转成二进制的算法是不断对2求余数,因此 不会存在无限值的状况;
2)浮点数的有效位及精度
浮点型所能表示的有效位是有限的,因此哪怕是整数,只要超出有效位数,也只能存储类似值,也就是该数值的最低有效位将会丢失,从而造精度丢失。 float类型的二进制有效位是24位,对应十进制的7 ~ 8位数字;double类型的二进制53位,对应十进制的10 ~ 11位数字。
double、float类型 所能表示的范围比int、long类型表示的范围要广,也浮点类型属于大类型。可是,并不能完美地表整形,浮点类型的精度丢失会形成一些问题。
public static void main(String[] args) {
int a = 3000000;
int b = 30000000;
float f1 = a;
float f2 = b;
System.out.println("3000000==3000001 "+(f1==f1+1));
System.out.println("30000000==30000001 "+(f2==f2+1));
System.out.println("3000000的有效二进制位数:"+ Integer.toBinaryString(a).length());
System.out.println("30000000的有效二进制位数:"+ Integer.toBinaryString(b).length());
}
复制代码
运行结果:
3000000 == 3000001 false 30000000 == 30000001 true 3000000的有效二进制位数: 22 30000000的有效二进制位数: 25
上面的例子很好体现了精度丢失所带来的后果:30000000==30000001
的比较竟然为true了。而形成这种结果的缘由就是 30000000的有效二进制位数是25位,超出了float所能表示的有效位24位,最后一位就被舍去,因此就形成在刚加的1也被舍去,所以30000000的加一操做先后的浮点型表示是同样的。
固然,**并非超出浮点型的有效位就不能精确表示,其实,主要看的是最高有效位与最低非0有效位之间的 “间隙”,若是间隙的在浮点型的有效位数内,天然能够精确表示,由于舍去的低有效位都是0,天然就无所谓了。**若是上面的例子的浮点型用的是double就不会丢失精度了,由于double的精度是52位。
3)解决浮点型精度丢失的问题
浮点型带来精度丢失的问题是很让人头痛的,因此通常状况下,在程序中是不会使用float、double来存储比较大的数据。而商业计算每每要求结果精确。《Effactive Java》书中有一句话:
float和double类型的主要设计目标是为了科学计算和工程计算
JDK为此提供了两个高精度的大数操做类给咱们:BigInteger、BigDecimal。
出处:http://www.cnblogs.com/jinggod/p/8424583.html
文章有不当之处,欢迎指正,你也能够关注个人微信公众号:
好好学java
,获取优质资源。