[Java] 作业2答疑

来源:互联网 发布:买到淘宝假货怎么投诉 编辑:程序博客网 时间:2024/05/22 00:45

关于溢出的问题,可以先翻书、百度,了解一下预备知识;

关于程序是否能通过编译、运行时时候会异常退出的问题,可以自行用eclipse验证。


Q19. What is the value of i printed?

public class Test {public static void main(String[] args) {int j = 0;int i = j++ + j * 5;System.out.println("What is i? " + i);}}
要先明确一点,在写代码的过程中,我们一般不会写int i = j++ + j * 5; 这样比较让人有歧义、迷惑的语句,这样会使得程序的可读性下降;

另一方面,这种题型的存在,是为了考察大家对优先级的理解。

大家可以找到书里关于操作符的优先级与结合性的表格。会发现++, *和+的优先级是依次降低的。所以程序的执行顺序是:

int i = j++ + j * 5;// j++先执行,j变成1, 返回0;// 然后j * 5 == 1 * 5, 返回5;// 最后int i = 0 + 5 = 5.


Q21. What is y displayed in the following code?

public class Test {public static void main(String[] args) {int x = 1;int y = x + x++;System.out.println("y is " + y);}}

OS: 我在StackOverflow上问了这个问题,结果因为"duplicate questions"我被扣了4分的reputation...


在解答这题前,我想先介绍三个概念:优先级(precedence), 结合性(associativity), 和表达式求值顺序(expression evaluation order).

优先级(precendence)

优先级解决的是,操作符优先级不同时的执行顺序:

A() + B() + C() * D().

由于乘法的优先级高于加法,我们可以将表达式写成 A() + B() + (C() * D()).


结合性(associativity)

结合性解决的是,操作符优先级相同时的执行顺序:

由于加法的结合性是左集合,那么我们有

((A() + B()) + (C() * D()))

通过优先级,我们保证了左边的(第一个)加法,在第二个加法之前被执行;

通过优先级,我们保证了乘法在第二次加法之前被执行。

但是上述两种约束,并没有规定乘法必须发生在第一个加法之前。


同时,考虑下述代码:

a = A() // 1b = B() // 2c = C() // 3d = D() // 4sum = a + b //5product = c * dresult = sum + product

事实上,语句1, 2, 3, 4的执行顺序是可以任意打乱的,至少只要它们在语句5之前执行完即可。Evaluation Order正是规定了表达式的求值顺序。

求值顺序(evaluation order)

Evaluation Order规定了在Java中,表达式从左往右求值。

所以按照我的理解,对于A() + B() + C() * D()的计算顺序应该是

a = A()b = B()c = C()d = D()sum = a + b // 1product = c * d // 2result = sum + product
其中第一次加法(1)和乘法(2)的顺序是可以相互替换的。


讲完了优先级、结合性和求值顺序,我们就可以有理有据地,毫无歧义地,获得一个表达式的值。

一时间没能理解这三个概念是正常的,记住表达式是从左往右求值的,然后慢慢从题目中验证这三个概念即可。


回到原题Q21.

int x = 1;int y = x + x++;// ++优先级高于+, 表达式y = x + (x++)// 表达式从左往右求值://     1. 左边的x先被求值,表达式变成 y = 1 + (x++);//     2. 右边的x++再被求值,x自增成2, 表达式变成y = 1 + 1 = 2.

Q25. What is the value of (double)(5/2)?

整数除整数,仍为整数。

10 / 9 = 1,

5 / 9 = 0,

5 / 2 = 2.


Q31. Suppose i is an int type variable. Which of the following statements display the character whose Unicode is stored in variable i?

a. System.out.println(i);

b. System.out.println((char)i);

c. System.out.println((int)i);

d. System.out.println(i + " ");


char在内存中的表示

在Java中,char是用16个比特位(bit)保存的,bit非1即0. 所以char的表示范围是 0000_0000_0000_0000 ~ 1111_1111_1111_1111, 十进制表示是0 ~ 65535.

一方面,在我们使用println输出一个char类型时,我们可以在屏幕上看到它的字符表示;

另一方面,在计算机在内部,对char和int一视同仁,都用二进制的比特位对它们进行表示。不同的是,计算机用16位bit表示char, 但可能用32位或者64位表示int(或者long).

所以,char和int是可以相互转换的。


char和int间的转换

上面说到了,char和int在内存中都是用二进制表示的。那么它们之间是可以相互转换的。

大家可以去百度一下ASCII码表,码表中给出了字符类型(char)与整型间的对应关系。比如说,'a'的十进制整型表示是97, 'b'的十进制整型表示是98. 大家可以在eclipse下运行如下程序:

public class CharAndInt {public static void main(String[] args) {char c1 = 'a';System.out.println((int) c1);      // 输出 97System.out.println(c1 + 1);        // 输出 98int i1 = 97;System.out.println((char) i1);     // 输出 aSystem.out.println((char) (i1+1)); // 输出 b}}

注意到,(int) 是强制转换符,(int) c1的含义是将c1强制转换成int类型,println则将接收到一个int类型,将这个int类型以十进制输出;

(char) i1则是将i1强制转成成char类型,println将接收到一个char类型,输出这个char的字符表示(Unicode表示)。


回到原题Q31

我们已知println会根据接收到的类型,打印出相应的内容。

如果println接受到的是一个int类型(如a, c选项),那么println就输出这个int类型的十进制表示;

如果println接受到的是一个char类型(如b选项),那么println就输出这个char类型对应的字符;

如果println接受到的是一个String类型(如d选项),那么println久输出这个字符串。


Q35. Which of the following statement is correct?

把选项复制到eclipse下运行就可以知道答案,原因在Q31中解释了。


Q39. Which of the following statement is false?

答案D错误。

x > 0 || x < 10 && y < 0// &&优先级比||高,这个表达式等价于x > 0 || (x < 10 && y < 0) // 亦即x<0和y<0的逻辑与关系(&&)先被计算// 再计算逻辑或关系(||)(x > 0 || x < 10) && y < 0// 这个先计算了||, 之后才计算&&


Q42. 下面哪个是错误的字符常量?

在Q31中讲到,char在内存中用16个bit保存。

所以我们可以用'\uxxxx'来表示,这个char在Unicode字符集下的十六进制:

    - 每个x都是0-9, a-f或A-F的十六进制表示,代表了内存中的4个bit

    - 有且只有4个x, 总共代表16个bit.


0 0