表达式之谜

以下内容全部来自《java解惑》

1、奇数性

这个谜题主要是提醒我们要注意如何来判断一个数是不是奇数

比如:

i % 2 == 1

这个是否可以成功判断?

如果i是负数呢?显然会是-1

所以我更喜欢:i % 2 != 0

还有一种看起来比较high的:i&1 != 0

2、找零时刻

这个谜题是货币计算的,由于浮点数在计算机中并不会精确保存,所以,有时候难免有误差,因此问题也就产生了

如:System.out.println(2.00-1.10);

输出的不是你想象的0.90,而是一个近似值0.8999999999999999

操作这些需要很精确的数据时我们最好采用BigDecimal数据类型。

BigDecimal类型定义了add,subtract,multiply,divide方法来进行精确的四则计算。

如上例:

System.out.println(BigDecimal("2.00").subtract(BigDecimal("1.10')));

这样就OK了

所得提示:在需要精确的地方,要避免使用float ,double,对于货币,要使用int,long,BigDecimal。

3、长整除

这个谜题是关于long和int的混合计算的

如:long tmp = 24*23*34*4*5000000;

以及long tmp= 1L * 24*23*34*4*5000000;

这两个表达式的tmp一样吗?相信你知道了吧!

提示:操作大数据时,千万要提防溢出!

4、初级问题

System.out.println(12345+5432l);

等于多少?是66666?

注意l和1的区别,其实这道题是在提示我们,当要表示长整型时要用L,而不是l

5、十六进制的趣事

System.out.println(Long.toHexString(0x100000000L + 0xcafebabe))

会输出多少呢?cafebabe

为什么呢?

十进制可以清楚的表示一个负数,而对于八进制或者十六进制而言,负数的表示不那么清楚,比如上面的0xcafebabe是正数还是负数呢?

我们需要知道内存里面存的时候怎么表示正负数:如果十六进制和八进制字面常量的最高位被置位了,那么它们就表示负数。因此0xcafebabe是负数。

其次我们还需要知道:符号扩展,因为第一个操作数是long型,所以int应该进行扩展,而由于int是有符号的,所以要进行有符号扩展,即是负数的话,前面的扩展位都是1

因此就有了下面的计算:

    0xffffffffcafebabe

+  0x0000000100000000

=   0x00000000cafebabe

提示:

      1、对于十六进制或八进制运算,要注意符号位

      2、扩展类型的时候注意是不是有符号扩展

      3、运算时,最好避免两个不一样类型的数据进行运算

6、多重转型

System.out.println((int)(char)(byte)-1);

输出什么?65535

int->byte:转换的时候直接截取第八位即可,依然是-1

byte->char:它们不能直接转,因为byte有符号而char是无符号的,可以化成两个动作,byte->int->char,byte->int,有符号扩展(-1),int->char,直接截取低十六位为0xFFFF(0xFFFFFFFF),即65535。

char->int:直接补零,还是原数值。依然是65535.

提示:如果最初的数值有符号,那么就执行符号扩展,如果它是char,那么不管它将被转换成什么类型,都执行零扩展。

7、互换内容

int x = 1984;//0x7c0

int y = 2001;//0x7d1

x^=y^=x^=y;

System.out.println("x="+x+";y="+y);

打印多少?x=0;y=1984

这个就是告诉我们,不可再单个表达式里对相同对象赋值两次。

8、dos equis

如下:

int  i = 0;

char x = ‘X’;

System.out.println(true?x:0);

System.out.println(false?i:x);

打印什么?X88

需要注意到的是i和x的类型不一样,平常使用的都是相同类型的数据,所以不会出现这些似非而是的东西。

看三条规则:

 (a)如果两个操作数的类型相同,表达式的类型是确定的,

 (b)如果一个操作数的类型是T,T可以是short,char,byte,而另一个操作数是int常量,那么最终的类型是T

 (c)如果两个操作数的类型不一样,需要进行类型扩展,最终的表达式类型是扩展类型。

因此上述两个输出语句,第一个类型是char,而第二个类型是int,故打印了X88

提示:在表达式语句中最好使用两个类型相同的操作数,当然了一般我们也是无意中这样做的。

9、半斤

给出变量的声明,使x+=i合法,而使x=x+i不合法;

这是考察复合赋值符和简单赋值的区别。

java语言规范说明复合赋值E1 op= E2等价于简单赋值E1=(T)(E1 op E2),其中T是E1的类型。

看过之后,就会发现其实复合赋值符不仅简单的进行运算,而且还会自动进行类型转换。

因此声明为short x = 0;int i=123456;可以使得x+=i合法,而使x=x+i不合法

提示:请不要将复合赋值操作符作用于byte,short,char类型变量。

10、八两

与谜题9相反,给出声明。使得x = x + i合法,而使得x+=i不合法

复合赋值操作符:要求两个操作数都是基本的数据类型;

简单赋值符:允许左侧为对象引用,所以可以使用它们来表示任何想要表示的内容,只要表达式的右侧与左侧的变量是赋值兼容的即可

Object x= “sdjhg”;

String i= “sadgag”;

这样的声明可以使x=x+i合法,而使x+=i不合法。


综观本章,都是着眼于一些细小而神奇的地方,有些地方其实,我们已经在避免,几乎不会使用那样的表达,比如条件表达式,半斤八两这样的赋值。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值