下面这个示例展示了哪些基本数据类型能用于哪些特定的操作符。基本上这是一个不断重复的示例,只是每次使用了不同的基本数据类型。程序能正常编译,因为那些会导致编译失败的行已经用//-注释掉了。
// operators/AllOps.java// 对每个基本数据类型都测试一遍所有操作符// 以此显示哪些能被Java编译器所接受public class AllOps {// boolean类型测试void f(boolean b) {}void boolTest(boolean x, boolean y) {// 算术操作符://- x = x * y;//- x = x / y;//- x = x % y;//- x = x + y;//- x = x - y;//- x++;//- x--;//- x = +y;//- x = -y;// 关系操作符和逻辑操作符://- f(x > y);//- f(x >= y);//- f(x < y);//- f(x <= y);f(x == y);f(x != y);f(!y);x = x && y;x = x || y;// 按位操作符://- x = ~y;x = x & y;x = x | y;x = x ^ y;//- x = x << 1;//- x = x >> 1;//- x = x >>> 1;// 复合赋值://- x += y;//- x -= y;//- x *= y;//- x /= y;//- x %= y;//- x <<= 1;//- x >>= 1;//- x >>>= 1;x &= y;x ^= y;x |= y;// 类型转换://- char c = (char)x;//- byte b = (byte)x;//- short s = (short)x;//- int i = (int)x;//- long l = (long)x;//- float f = (float)x;//- double d = (double)x;}void charTest(char x, char y) {// 算术操作符:x = (char)(x * y);x = (char)(x / y);x = (char)(x % y);x = (char)(x + y);x = (char)(x - y);x++;x--;x = (char) + y;x = (char) - y;// 关系操作符与逻辑操作符:f(x > y);f(x >= y);f(x < y);f(x <= y);f(x == y);f(x != y);//- f(!x);//- f(x && y);//- f(x || y);// 按位操作符:x= (char)~y;x = (char)(x & y);x = (char)(x | y);x = (char)(x ^ y);x = (char)(x << 1);x = (char)(x >> 1);x = (char)(x >>> 1);// 复合赋值:x += y;x -= y;x *= y;x /= y;x %= y;x <<= 1;x >>= 1;x >>>= 1;x &= y;x ^= y;x |= y;// 类型转换://- boolean bl = (boolean)x;byte b = (byte)x;short s = (short)x;int i = (int)x;long l = (long)x;float f = (float)x;double d = (double)x;}void byteTest(byte x, byte y) {// 算术操作符:x = (byte)(x* y);x = (byte)(x / y);x = (byte)(x % y);x = (byte)(x + y);x = (byte)(x - y);x++;x--;x = (byte) + y;x = (byte) - y;// 关系操作符与逻辑操作符:f(x > y);f(x >= y);f(x < y);f(x <= y);f(x == y);f(x != y);//- f(!x);//- f(x && y);//- f(x || y);// 按位操作符:x = (byte)~y;x = (byte)(x & y);x = (byte)(x | y);x = (byte)(x ^ y);x = (byte)(x << 1);x = (byte)(x >> 1);x = (byte)(x >>> 1);// 复合赋值:x += y;x -= y;x *= y;x /= y;x %= y;x <<= 1;x >>= 1;x >>>= 1;x &= y;x ^= y;x |= y;// 类型转换://- boolean bl = (boolean)x;char c = (char)x;short s = (short)x;int i = (int)x;long l = (long)x;float f = (float)x;double d = (double)x;}void shortTest(short x, short y) {// 算术操作符:x = (short)(x * y);x = (short)(x / y);x = (short)(x % y);x = (short)(x + y);x = (short)(x - y);x++;x--;x = (short) + y;x = (short) - y;// 关系操作符与逻辑操作符:f(x > y);f(x >= y);f(x < y);f(x <= y);f(x == y);f(x != y);//- f(!x);//- f(x && y);//- f(x || y);// 按位操作符:x = (short) ~ y;x = (short)(x & y);x = (short)(x | y);x = (short)(x ^ y);x = (short)(x << 1);x = (short)(x >> 1);x = (short)(x >>> 1);// 复合赋值:x += y;x -= y;x *= y;x /= y;x %= y;x <<= 1;x >>= 1;x >>>= 1;x &= y;x ^= y;x |= y;// 类型转换://- boolean bl = (boolean)x;char c = (char)x;byte b = (byte)x;int i = (int)x;long l = (long)x;float f = (float)x;double d = (double)x;}void intTest(int x, int y) {// 算术操作符:x = x * y;x = x / y;x = x % y;x = x + y;x = x - y;x++;x--;x = +y;x = -y;// 关系操作符与逻辑操作符:f(x > y);f(x >= y);f(x < y);f(x <= y);f(x == y);f(x != y);//- f(!x);//- f(x && y);//- f(x || y);// 按位操作符:x = ~y;x = x & y;x = x | y;x = x ^ y;x = x << 1;x = x >> 1;x = x >>> 1;// 复合赋值:x += y;x -= y;x *= y;x /= y;x %= y;x <<= 1;x >>= 1;x >>>= 1;x &= y;x ^= y;x |= y;// 类型转换://- boolean bl = (boolean)x;char c = (char)x;byte b = (byte)x;short s = (short)x;long l = (long)x;float f = (float)x;double d = (double)x;}void longTest(long x, long y) {// 算术操作符:x = x * y;x = x / y;x = x % y;x = x + y;x = x - y;x++;x--;x = +y;x = -y;// 关系操作符与逻辑运算符:f(x > y);f(x >= y);f(x < y);f(x <= y);f(x == y);f(x != y);//- f(!x);//- f(x && y);//- f(x || y);// 按位操作符:x = ~y;x = x & y;x = x | y;x = x ^ y;x = x << 1;x = x >> 1;x = x >>> 1;// 复合赋值:x += y;x -= y;x *= y;x /= y;x %= y;x <<= 1;x >>= 1;x >>>= 1;x &= y;x ^= y;x |= y;// 类型转换://- boolean bl = (boolean)x;char c = (char)x;byte b = (byte)x;short s = (short)x;int i = (int)x;float f = (float)x;double d = (double)x;}void floatTest(float x, float y) {// 算术操作符:x = x * y;x = x / y;x = x % y;x = x + y;x = x - y;x++;x--;x = +y;x = -y;// 关系操作符与逻辑操作符:f(x > y);f(x >= y);f(x < y);f(x <= y);f(x == y);f(x != y);//- f(!x);//- f(x && y);//- f(x || y);// 按位操作符://- x = ~y;//- x = x & y;//- x = x | y;//- x = x ^ y;//- x = x << 1;//- x = x >> 1;//- x = x >>> 1;// 复合赋值:x += y;x -= y;x *= y;x /= y;x %= y;//- x <<= 1;//- x >>= 1;//- x >>>= 1;//- x &= y;//- x ^= y;//- x |= y;// 类型转换://- boolean bl = (boolean)x;char c = (char)x;byte b = (byte)x;short s = (short)x;int i = (int)x;long l = (long)x;double d = (double)x;}void doubleTest(double x, double y) {// 算术操作符:x = x * y;x = x / y;x = x % y;x = x + y;x = x - y;x++;x--;x = +y;x = -y;// 关系操作符与逻辑操作符:f(x > y);f(x >= y);f(x < y);f(x <= y);f(x == y);f(x != y);//- f(!x);//- f(x && y);//- f(x || y);// 按位操作符://- x = ~y;//- x = x & y;//- x = x | y;//- x = x ^ y;//- x = x << 1;//- x = x >> 1;//- x = x >>> 1;// 复合赋值:x += y;x -= y;x *= y;x /= y;x %= y;//- x <<= 1;//- x >>= 1;//- x >>>= 1;//- x &= y;//- x ^= y;//- x |= y;// 类型转换://- boolean bl = (boolean)x;char c = (char)x;byte b = (byte)x;short s = (short)x;int i = (int)x;long l = (long)x;float f = (float)x;}}
注意 boolean 类型是有限制的。我们只能赋予它 true 和 false 值,并测试它是真还是假,但不能将 boolean 值相加,或对 boolean 值执行其他任何运算。
在 char、byte 和 short 中,你可以看到算术操作符对数据类型的提升效果。对这些类型进行任何算术运算,都会获得一个 int 结果,如果想把这个结果赋给原来的类型,则必须显式地进行类型转换(窄化转型可能会造成信息丢失)。对于 int 值则不需要进行类型转化,因为所有数据都已经是 int 类型的了。但不要误以为一切都是安全的,如果对两个足够大的 int 数值执行乘法运算,结果可能会溢出。下面这个示例展示了这一点:
// operators/Overflow.java
// 惊讶吧!Java允许溢出
public class Overflow {
  public static void main(String[] args) {
    int big = Integer.MAX_VALUE;
    System.out.println("big = " + big);
    int bigger = big * 4;
    System.out.println("bigger = " + bigger);
  }
}
/* 输出:
big = 2147483647
bigger = -4
*/
这里编译器不会有错误提示或警告信息,运行时也不会出现异常。
对于 char、byte 或者 short,复合赋值并不需要类型转换。尽管它们都会做类型提升,并获得与直接算术运算相同的结果。而省略类型转换肯定使代码更简洁了。
除 boolean 类型以外,任何基本类型都可以转换为其他基本类型。再次提醒,当某种类型转换成一种较小的类型时,你必须了解窄化转型的效果,否则可能会在类型转换过程中不知不觉地丢失了信息。
