1 java puzzler 5
负的十进制数可以用一个减号表示。但是16进制和8进制字面常量的最高位被置位了,那么他就是负数。
打印结果:
0xcafebabe 在执行加法的时候,提升为长整型,即0xffffffffcafebabe,它和0x100000000L相加,高32位变为全零,剩下正整数cafebabe。
public static void main(String[] args) {
byte b = (byte) 0xff;
byte b1 = (byte) -1;
byte b2 = (byte) 1;
System.out.println(b1); // -1
System.out.println(Integer.toHexString(b1)); // ffffffff
System.out.println(b); // -1
System.out.println(b1 & 0xff); // 255
System.out.println(b2 << 1); // 2
System.out.println(b2 << 8 ); // 256
System.out.println(Long.toHexString(0x100000000L + 0xcafebabe)); // cafebabe
System.out.println(Integer.toHexString(0xcafebabe)); // cafebabe
System.out.println(Long.toHexString(0xcafebabe)); // ffffffffcafebabe
System.out.println(0xcafebabe); // -889275714
System.out.println((long)0xcafebabe); // -889275714
System.out.println(Long.toHexString((long)0xcafebabe)); // ffffffffcafebabe
System.out.println(Long.toHexString(0x100000000L)); // 100000000
System.out.println(Byte.toString((byte)0xff)); // -1
System.out.println((byte)0xff + (byte)1); // 0
}
2 java puzzler 6
从byte到char的转换不是一个拓宽原生类型转换,而是一个拓宽并窄化原生类型的转换:byte被转换成int,而后int转换成char。
int类型的常量-1 先被转换成byte, 表示为0xff,然后强转成char的过程是,先拓宽到int,即0xffffffff,在转换成char类型,截断高2个字节,保留低2字节,0xffff,即char类型的65535。然后强转成int类型,值还是65535。
(1)将char转换成更宽的类型 int i = c & 0xffff; // 不发生符号扩展
或者 是 int i = c; // 不发生符号扩展
(2)将char转换成更宽的类型,并期望有符号扩展,应该添加注释
int i = (short) c; //有符号扩展
(3)将byte转换成char,不希望符号扩展,全都转换成整数
char c = (char) (b & 0xff);
(4)将byte转换成char,有符号扩展
char c = (char) b;
打印结果
3 java puzzler 8
?: 运算符(条件表达式)结果类型确定规则:
(1)如果第二个和第三个操作数具有相同的类型,那么它就是条件表达式的类型。
(2)如果一个操作数的类型是T,T 表示byte、short 或char,而另一个操作数是一个int 类型的常量表达式,它的值是可以用类型T 表示的,那么条件表达式的类型就是T。
(3)否则,将对操作数类型运用二进制数字提升,而条件表达式的类型就是第二个和第三个操作数被提升之后的类型。
执行结果:
上面的运算,在迭代过程中,b扩展成整形Int,[-128, 127],而0x99等于153,迭代结束,条件不能满足,所以不打印OK。
修改成(b & 0xff) ,则迭代范围是[-128, 127),迭代比较值( b & 0xff)范围[128, 255]和[0, 127),因此何以打印OK。
4 复合赋值表达式自动地将它们所执行的计算的结果转型为其左侧变量
java puzzler 10
(1)复合赋值操作符要求两个操作数都是原始类型的,例如int,或包装了的原始类型,例如Integer,但是有一个例外:如果在+=操作符左侧的操作数是String类型的,那么它允许右侧的操作数是任意类型,在这种情况下,该操作符执行的是字符串连接操作。
(2)简单赋值操作符(=)允许其左侧的是对象引用类型,这就显得要宽松许多了:你可以使用它们来表示任何你想要表示的内容,只要表达式的右侧与左侧的变量是赋值兼容的即可。
例子 short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
short s1 = 1; s1 = s1 + 1; (s1+1运算结果是int型,需要强制转换类型)
short s1 = 1; s1 += 1;(可以正确编译)