=
1.2、算术操作符boolean flag1=true && false && true; boolean flag2=true & false & true;计算flag1会短路,计算flag2不会短路
//未丢失信息: float f=1f; int a=(int)f; //丢失信息: float f=1.1f; int a=(int)f;3.3、类型三
//丢失信息: int a=0x1ff; byte b=(byte)a; //那么截取低端位8位二进制位,得到b=0xff。 //未丢失信息: int a=0x1f; byte b=(byte)a; //那么截取低端位8位二进制位,得到b=0x1f。浮点型——》浮点型:如果是扩展转换,不丢失信息;如果是窄化转换,处理方式按照IEEE754标准规范[1],有可能丢失信息。
byte ba = 1; byte bb = 2; //算术操作符的例子,编译错误。因为:右边表达式中ba和bb会被隐式扩展成int型,而左边变量为byte型 byte bc = ba + bb; byte bd = ba - bb; byte be = ba * bb; byte bf = ba / bb; byte bg = ba % bb; //按位操作符的例子,编译错误。因为:右边表达式中ba和bb会被隐式扩展成int型,而左边变量为byte型 byte bh = ba & bb; //移位操作符的例子,编译错误。因为:右边表达式中ba和bb会被隐式扩展成int型,而左边变量为byte型 byte bi = ba >> bb;4.2、表达式中最大的数据类型决定了最终结果的数据类型
//byte型的a被隐式扩展成int型 byte a=10; int b=a; //int型的b被隐式扩展成long型 long c=10; long d=b+c;又比如操作符两边都为浮点型,其中一边是float,另一边是double,那么float类型变量会被隐式扩展成double类型。
数值直接常量隐含对应一个基本类型的变量。关于数值直接常量隐含对应一个基本类型的变量有以下3条规则:
1、在整型情形下(十六进制数值常量,八进制数值常量,十进制数值常量),数值直接常量对应的基本类型是int,通过在数值常量后加"l(或者L)"后缀,可以使得对应的基本类型是long。
在浮点型情形下(十进制数值常量),数值直接常量对应的基本类型是double,通过在数值常量后加"f(或者F)"后缀,可以使得对应的基本类型是float。通过在数值常量后加"d(或者D)"后缀,可以使得对应的基本类型是double。
比如有以下代码:
public class Main { void f1(char x) { System.out.println("f1(char)"); } void f1(byte x) { System.out.println("f1(byte)"); } void f1(short x) { System.out.println("f1(short)"); } void f1(int x) { System.out.println("f1(int)"); } void f1(long x) { System.out.println("f1(long)"); } void f1(float x) { System.out.println("f1(float)"); } void f1(double x) { System.out.println("f1(double)"); } public static void main(String[] args) { Main main = new Main(); main.f1(5); //main.f1(0x1fffffffff); } }运行后得到的结果如下:
f1(int)从中可知,数值直接常量5对应的基本类型是int。
将注释语句的注释去掉,可以发现,编译器报如下错误:
Integer number too large
这是因为数值直接常量“0x1fffffffff”对应的基本类型是int,而它超出了int的表示范围,因而报出如上错误,如果在“0x1fffffffff”后加上L,那么显式指定对应的基本类型是long,编译就能通过。
又比如有以下代码:
public class Main { void f1(char x) { System.out.println("f1(char)"); } void f1(byte x) { System.out.println("f1(byte)"); } void f1(short x) { System.out.println("f1(short)"); } void f1(int x) { System.out.println("f1(int)"); } void f1(long x) { System.out.println("f1(long)"); } void f1(float x) { System.out.println("f1(float)"); } void f1(double x) { System.out.println("f1(double)"); } public static void main(String[] args) { Main main = new Main(); main.f1(5.0); main.f1(3.5E39); //main.f1(3.5E39F); } }
运行后得到结果如下:
f1(double) f1(double)从中可知,数值直接常量5.0和3.5E39对应的基本类型是double。
将注释语句的注释去掉,可以发现,编译器报如下错误:
Floating point number too large这是因为显式指定数值直接常量“3.5E39F“对应的基本类型是float,而它超出了float的表示范围,因而报出如上错误。
2、在Java程序中碰到数值直接常量,以其隐含对应的基本类型变量的身份去考虑,可以帮助我们理解,减少错误的发生。
3、关于“在Java程序中碰到数值直接常量,以其隐含对应的基本类型变量的身份去考虑”有一个例外:当数值直接常量为整型,且隐含对应的基本类型是int型,去给byte类型,short类型,char类型变量赋值,且数值直接常量的数值在相应变量的表示范围内,虽说此时仍旧可以以数值直接常量隐含对应的int类型变量身份去考虑问题,但是却不像真正的int类型变量那样需要显式窄化转换,可以认为这个特殊情况由编译器负责处理。
除此情况外,当碰到数值直接常量时,就完全可以以其隐含对应的基本类型变量的身份去考虑问题,该显式转换就显式转换,无需显式转换就不需显式转换。
可见如下代码所示例子:
public class Main { public static void main(String[] args) { byte b; short s; char c; int i; long l; float f; double d; int itmp; long ltmp; float ftmp; double dtmp; // 分隔符------------------------ // 无需显式转换,验证的确无需显式转换 f = 10; f = 10L; d = 10; d = 10L; f = 10.0F; d = 10.0; d = 10.0D; d = 10.0F; // 验证 itmp = 10; ltmp = 10L; ftmp = 10.0F; dtmp = 10.0D; f = itmp; f = ltmp; d = itmp; d = ltmp; f = ftmp; d = dtmp; d = ftmp; // 分隔符------------------------ // 需要显式转换,验证的确需要显式转换 f = (float) 10.0; // 验证 dtmp = 10.0; f = (float) dtmp; // 分隔符------------------------ // 无需显式转换,验证的确无需显式转换 i = 10; l = 10L; // 验证 itmp = 10; ltmp = 10L; i = itmp; l = ltmp; // 分隔符------------------------ // 需要显式转换,验证的确需要显式转换 b = (byte) 10.0; b = (byte) 10.0D; s = (short) 10.0; s = (short) 10.0D; c = (char) 10.0; c = (char) 10.0D; i = (int) 10.0; i = (int) 10.0D; l = (long) 10.0; l = (long) 10.0D; // 验证 ftmp = 10.0F; dtmp = 10.0D; b = (byte) ftmp; b = (byte) dtmp; s = (short) ftmp; s = (short) dtmp; c = (char) ftmp; c = (char) dtmp; i = (int) ftmp; i = (int) dtmp; l = (long) ftmp; l = (long) dtmp; // 分隔符------------------------ // 需要显式转换,验证的确需要显式转换 b = (byte) 2100000000; b = (byte) 2100000000L; s = (short) 2100000000; s = (short) 2100000000L; c = (char) 2100000000; c = (char) 2100000000L; // 验证 itmp = 2100000000; ltmp = 2100000000L; b = (byte) itmp; b = (byte) ltmp; s = (short) itmp; s = (short) ltmp; c = (char) itmp; c = (char) ltmp; // 分隔符------------------------ // 需要显式转换,验证“的确需要显式转换” b = (byte) 10L; s = (short) 10L; c = (char) 10L; ltmp = 10L; b = (byte) ltmp; s = (short) ltmp; c = (char) ltmp; // 分隔符------------------------ // 本应显式转换,却由编译器进行处理,验证“的确是由编译器处理本应的显式转换” b = 10; s = 10; c = 10; // 验证 itmp = 10; b = (byte) itmp; s = (short) itmp; c = (char) itmp; } }
[1]http://stackoverflow.com/questions/10075058/converting-from-double-to-float-in-java
[2]http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html