下面这个示例展示了哪些基本数据类型能用于哪些特定的操作符。基本上这是一个不断重复的示例,只是每次使用了不同的基本数据类型。程序能正常编译,因为那些会导致编译失败的行已经用//-注释掉了。
// 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 类型以外,任何基本类型都可以转换为其他基本类型。再次提醒,当某种类型转换成一种较小的类型时,你必须了解窄化转型的效果,否则可能会在类型转换过程中不知不觉地丢失了信息。