编辑: AA003 2013-04-07

200 倍的数值. 从int 提升到 long 是一种拓宽原始类型转换 (widening primitive conversion) , 它保留了(不正确的)数值.这个值之后被 MILLIS_PER_DAY 整除,而MILLIS_PER_DAY 的计算是正确的,因为它适合 int 运算.这样整除的结果就得 到了 5. 那么为什么计算会是以 int 运算来执行的呢?因为所有乘在一起的因子都是 int 数值.当你将两个 int 数值相乘时,你将得到另一个 int 数值.Java 不具有目 标确定类型的特性,这是一种语言特性,其含义是指存储结果的变量的类型会影 响到计算所使用的类型. 通过使用 long 常量来替代 int 常量作为每一个乘积的第一个因子,我们就可以 很容易地订正这个程序.这样做可以强制表达式中所有的后续计算都用 long 运 作来完成.尽管这么做只在 MICROS_PER_DAY 表达式中是必需的,但是在两个乘 积中都这么做是一种很好的方式.相似地,使用 long 作为乘积的 第一个 数 值也并不总是必需的, 但是这么做也是一种很好的形式. 在两个计算中都以 long 数值开始可以很清楚地表明它们都不会溢出. 下面的程序将打印出我们所期望的 1000: public class LongDivision{ public static void main(String args[ ]){ final long MICROS_PER_DAY = 24L *

60 *

60 *

1000 * 1000;

final long MILLIS_PER_DAY = 24L *

60 *

60 * 1000;

System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY);

} iTePub.Net-Collect } 这个教训很简单:当你在操作很大的数字时,千万要提防溢出――它可是一个缄 默杀手.即使用来保存结果的变量已显得足够大,也并不意味着要产生结果的计 算具有正确的类型.当你拿不准时,就使用 long 运算来执行整个计算. 语言设计者从中可以吸取的教训是: 也许降低缄默溢出产生的可能性确实是值得 做的一件事.这可以通过对不会产生缄默溢出的运算提供支持来实现.程序可以 抛出一个异常而不是直接溢出,就像 Ada 所作的那样,或者它们可以在需要的时 候自动地切换到一个更大的内部表示上以防止溢出,就像 Lisp 所作的那样.这 两种方式都可能会遭受与其相关的性能方面的损失. 降低缄默溢出的另一种方式 是支持目标确定类型,但是这么做会显著地增加类型系统的复杂度 谜题 谜题 谜题 谜题

4 4

4 4: : : :初级问题 初级问题 初级问题 初级问题 得啦,前面那个谜题是有点棘手,但它是有关整除的,每个人都知道整除是很麻 烦的.那么下面的程序只涉及加法,它又会打印出什么呢? public class Elementary{ public static void main(String[] args){ System.out.println(12345+5432l);

} } 从表面上看,这像是一个很简单的谜题――简单到不需要纸和笔你就可以解决 它. 加号的左操作数的各个位是从

1 到5升序排列的, 而右操作数是降序排列的. 因此,相应各位的和仍然是常数,程序必定打印 66666.对于这样的分析,只有 一个问题:当你运行该程序时,它打印出的是 17777.难道是 Java 对打印这样 的非常数字抱有偏见吗?不知怎么的,这看起来并不像是一个合理的解释. 事物往往有别于它的表象. 就以这个问题为例, 它并没有打印出我们想要的输出. 请仔细观察 + 操作符的两个操作数,我们是将一个 int 类型的

12345 加到了 long 类型的 5432l 上.请注意左操作数开头的数字

1 和右操作数结尾的小写字 母l之间的细微差异.数字

1 的水平笔划(称为 臂(arm) )和垂直笔划(称为 茎(stem) )之间是一个锐角,而与此相对照的是,小写字母 l 的臂和茎 之间是一个直角. 在你大喊 恶心! 之前,你应该注意到这个问题确实已经引起了混乱,这里确 实有一个教训: 在long 型字面常量中, 一定要用大写的 L, 千万不要用小写的 l. 这样就可以完全掐断这个谜题所产生的混乱的源头. System.out.println(12345+5432L);

下载(注:源文件不在本站服务器,都将跳转到源网站下载)
备用下载
发帖评论
相关话题
发布一个新话题