[Java] 作业2答疑

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

关于程序是否能通过编译、运行时时候会异常退出的问题,可以自行用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() // 1
b = B() // 2
c = C() // 3
d = D() // 4
sum = a + b //5
product = c * d
result = 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 // 1
product = c * d // 2
result = 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);      // 输出 97
		System.out.println(c1 + 1);        // 输出 98
		int i1 = 97;
		System.out.println((char) i1);     // 输出 a
		System.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.


实验2 异常 在实验1基础上, 定义一个异常类ScoreException,当输入的学生成绩不在[0,100]区间时,抛出该异常。 定义一个异常类StudentNumberException,当输入的学号不满足下述条件,则抛出该异常。条件为:??学号为11位??(学号为10位),第1位为2,第2位为0,其余位为数字0~9. 对Student和StudentTest类进行必要修改,提升程序的健壮性。 StudentTest类运行效果如下: 测试用例1: 请输入学生学号:2011211301 请输入学生姓名:王晓 请输入学生三门课成绩(数学,英语,科学):88,79,90 学生信息如下: 学号:2011211301 姓名:王晓 数学成绩:88 英语成绩:79 科学成绩:90 平均成绩:85.66666666666667 测试用例2: 请输入学生学号:1011211301 学号格式不正确,请重新输入 请输入学生学号:101121130x 学号格式不正确,请重新输入 请输入学生学号:2011211301 请输入学生姓名:王晓 请输入学生三门课成绩(数学,英语,科学):88,179,90 成绩数据有误,请重新输入 请输入学生三门课成绩(数学,英语,科学):88,-79,90 成绩数据有误,请重新输入 请输入学生三门课成绩(数学,英语,科学):88,79,90 学生信息如下: 学号:2011211301 姓名:王晓 数学成绩:88 英语成绩:79 科学成绩:90 平均成绩:85.66666666666667 作业命名: _学号(8位)_姓名_第几次作业(1位)_类名.java eg: _09211195_王晓_1_Student.java //定义Student类 _09211195_王晓_1_StudentList.java //定义StudentList类 为便于作业批改和查找,上传作业的时候,传.java文件,不要上传压缩包,一次作业可以有多个.java文件 为便于作业批改,要求源文件中的类名也需要和java文件名一致。如: public class _09211195_王晓_1_Student{ //略 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值