Java解惑学习有感(三)---循环之谜

谜题  24 : 尽情享受每一个字节

如何将byte类型的数值b与0x90做比较?

两种方式:

第一种方式:将int类型的0x90转变为byte类型

b == (byte)0x90

第二种方式:将b转变为int类型

b == (byte)0x90

若在循环之中,应将0x90定义成常量形式:

private static final byte TARGET = (byte)0x90;

谜题  25 :无情的增量操作

public class Increment {

public static void main(String[] args) {

int j = 0;
for (int i = 0; i < 100; i++)

j = j++;

System.out.println(j);

}

}

j=j++,这个操作会一直让j=0,而不会让j产生递增效果,如果想让其递增,则将该语句修改为j++即可

总结:不要在单个的表达式中对相同的变量赋值超过一次。对相同的变量进行多次赋值的表达式会产生混淆,并且很少能够产生你希望的行为。

谜题  26 :在循环中

public class InTheLoop {
public static final int END = Integer.MAX_VALUE;
public static final int START = END - 100;
public static void main(String[] args) {
int count = 0;
for (int i = START; i <= END; i++)
count++;
System.out.println(count);
}
}

上述代码将会无限循环,因为i是int类型,无法递增到比int类型的最大值还要大,当超过其最大值时,就会溢出,转变成最小值。

解决上述问题可以直接将i转换成long类型,或者用do while循环语句

int i = START;
do {
count++;
}while (i++ != END);

谜题  27 : 变幻莫测的 i i

常量-1 是所有 32 位都被置位的 int 数值(0xffffffff)。左移操作符将 0 移入到由移位所空出的右边的最低位,因此表达式(-1 << i)将 i 最右边的位设置为 0,并保持其余的 32 - i 位为 1。但是,如果试图对一个 int 数值移位 32 位,或者是对一个 long 数值移位 64 位,都只能返回这个数值自身的值。没有任何移位长度可以让一个 int 数值丢弃其所有的 32 位,或者是让一个 long数值丢弃其所有的 64 位。

谜题  28 : 循环者

浮点数操作返回的是最接近其精确的数学结果的浮点数值。一旦毗邻的浮点数值之间的距离大于 2,那么对其中的一个浮点数值加 1 将不会产生任何效果,因为其结果没有达到两个数值之间的一半。对于 float 类型,加 1 不会产生任何效果的最小级数是 2^25 ,即 33,554,432,即float f=33554432f;f==f+1;将会返回true;而对于 double 类型,最小级数是 2^54 ,大约是 1.8 × 10^16 ,即double d=2^54;d == d+1也会返回true

谜题  29 :循环者的新娘

1、如果 i 在循环开始之前被初始化为 NaN,那么终止条件测试(i != i)的计算结果就是 true,循环就永远不会终止。

2、一旦一个计算产生了 NaN,它就被损坏了,没有任何更进一步的计算可以修复这样的损坏。NaN 值意图使受损的计算继续执行下去,直到方便处理这种情况的地方为止。

3、float 和 double 类型都有一个特殊的 NaN 值,用来表示不是数字的数量。对于涉及 NaN 值的计算,其规则很简单也很明智,但是这些规则的结果可能是违背直觉的。

谜题  30 : 循环者的爱子

请提供一个对 i 的声明,将下面的循环转变为一个无限循环:
while (i != i + 0) {
}
与前一个谜题不同,你必须在你的答案中不使用浮点数。换句话说,你不能把 i
声明为 double 或 float 类型的。

事实上,i 可以被初始化为任何值,只要它是 String 类型的即可,例如:
String i = "Buy seventeen copies of Effective Java";

谜题  31 : 循环者的鬼魂

不要在 short、byte 或 char 类型的变量之上使用复合赋值操作符。因为这样的表达式执行的是混合类型算术运算,它容易造成混乱。更糟的是,它们执行将隐式地执行会丢失信息的窄化转型,其结果是灾难性的。


谜题  32 :循环者的诅咒

Integer i = new Integer(0);
Integer j = new Integer(0);

while (i <= j && j <= i && i != j) {
}

在jdk5.0之后,上述代码将会无限循环,前两个子表达式(i <= j 和 j <= i)在 i 和 j 上执行解包转换,并且在数字上比较所产生的 int 数值。i 和 j 都表示 0,所以这两个子表达式都被计算为 true。第三个子表达式(i != j)在对象引用 i 和 j 上执行标识比较,因为它们都初始化为一个新的 Integer 实例,因此,第三个子表达式同样也被计算为 true,循环也就永远地环绕下去了。

总之,当两个操作数都是被包装的数字类型时,数值比较操作符和判等操作符(!=和==)的行为存在着根本的差异:数值比较操作符执行的是值比较,而判等操作符执行的是引用标识的比较。


谜题  33 :循环者遇到狼人

Java 使用 2 的补码的算术运算,它是非对称的。对于每一种有符号的整数类型(int、long、byte 和 short),负的数值总是比正的数值多一个,这个多出来的值总是这种类型所能表示的最小数值。对 Integer.MIN_VALUE 取负值得到的还是它没有改变过的值,Long.MIN_VALUE 也是如此。对 Short.MIN_VALUE取负值并将所产生的 int 数值转型回 short,返回的同样是最初的值
(Short.MIN_VALUE)。对 Byte.MIN_VALUE 来说,也会产生相似的结果。更一般地讲,千万要当心溢出:就像狼人一样,它是个杀手。

谜题  34 : 被计数击倒了

当float类型的初始值接近于Integer.MAX_VALUE,它需要用 31 位来精确表示,而 float 类型只能提供24 位的精度,对如此巨大的一个 float 数值进行增量操作将不会改变其值

不要使用浮点数作为循环索引,因为它会导致无法预测的行为。如果你在循环体内需要一个浮点数,那么请使用 int 或 long 循环索引,并将其转换为float或double。在将一个int或long转换成一个float或double时,你可能会丢失精度,但是至少它不会影响到循环本身。当你使用浮点数时,要使用 double 而不是 float,除非你肯定 float 提供了足够的精度,并且存在强制性的性能需求迫使你使用 float。适合使用 float 而不是 double 的时刻是非常非常少的。

谜题  35 : 一分钟又一分钟

取余和乘法操作符具有相同的优先,因此在执行ms % 60*1000这一语句时,会执行ms%60先,取余后再乘以1000,如果要先进行乘法操作,则应该这样ms%(60*1000),或者将60*1000定义成一个常量


如果有疑问或者对本博文有何看法或建议或有问题的,欢迎评论,恳请指正!


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值