Java高级谜题86:有毒的括号垃圾
能否举一个合法的Java表达式的例子,可以通过给它的一个子表达式加圆括号使其非法,加圆括号只是为了表示赋值的顺序没有圆括号?
插入一对括号来注释现有的赋值顺序,似乎对程序的合法性没有影响。其实大多数情况下,真的没什么作用。然而,在两种情况下,插入一对看似无关紧要的括号可能会使一个合法的Java程序变得非法。这种奇怪的情况是由数值的二进制补码的不对称性引起的,如谜题33和谜题64中所讨论的。你可能认为int类型的最小负数的绝对值比int类型的正数的绝对值大1:integer . min _ value是-231,即-2147483648,而Integer。MAX_VALUE是231-1,即2,147,483,647。
Java不支持负的十进制文字常量;和intlong负常量由正十进制常量组成,前面是一元负运算符(-)。这种形式是由特殊的语言规则决定的:在int类型的十进制文字常量中,数字是2147483648。并且从0到2147483647的所有十进制文字常量都可以出现在任何可以使用int类型文字常量的地方,但是文字常量2147483648只能作为一元负运算符的操作数【JLS 3.10.1】。
一旦你知道了这个规则,这个难题就简单了。符号-2147483648构成一个合法的Java表达式,它由一元负运算符加上一个int文字常量2147483648组成。加一对括号来注释(不重要的)赋值顺序,也就是写——(2147483648),会打破这个规律。信不信由你,下面的程序肯定会有编译时错误。如果去掉括号,那么错误就没有了:
public class poisonparen {
int I =-(2147483648);
}
同样,上述情况也适用于长文字常量。下面的程序也会产生编译时错误,如果去掉括号,错误就会消失:
public class poisonparen {
long j =-(922372036854774808 l);
}
0条评论