Lab 2: Java 语法 & 面向对象初步

本次 Lab 时长为 2 周,DDL 为 9 月 25 日 23:59。😁

附件下载(包括问答题和实验报告模板):https://bhpan.buaa.edu.cn/link/AA96D0CA694BB74ABFA070F38B6C527AC6

1. 实验目的

  1. 掌握 Java 环境配置
  2. 使用 CMD 编译运行 Java 程序
  3. 使用 IDE 编译运行 Java 应用程序
  4. 理解 Java 语言中的关键字、标识符并能灵活使用
  5. 理解、掌握 Java 语言的简单数据类型并能灵活使用(重点强制类型转换)
  6. 理解引用数据类型,理解简单数据类型和引用数据类型的特点
  7. 理解、掌握 Java 语言中的运算符并能灵活使用
  8. 理解、掌握常量与变量的概念并能灵活使用
  9. 理解、掌握 Java 语言的流程控制(重点 switch case break 语句)并能灵活使用
  10. 理解、掌握 Java 语言的数组的声明、赋值及使用
  11. 理解掌握面向对象思维方式,确定问题域,使用面向对象思维解决实际问题

2. Class 初步

Question01

阅读下列 Java 源文件,并回答问题。将你的作答以文字或截图形式呈现。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Person {
void speakHello() {
System.out.print("您好,很高兴认识您");
System.out.println(" nice to meet you");
}
}

class Test {
public static void main(String[] args) {
Person zhang = new Person();
zhang.speakHello();
}
}

(1) 上述源文件的名字是什么?

(2) 编译上述源文件将生成几个字节码文件?这些字节码文件的名字都是什么?

(3) 在命令行执行 java Person 得到怎样的错误提示?执行 java test 得到怎样的错误提示?执行 java Test.class 得到怎样的错误提示?执行 java Test 得到怎样的输出结果?

3. Unicode 编码

Question02

看程序输出结果,并提交结果内容或截图

1
2
3
4
5
6
7
8
public class Unicode {
public static void main(String[] args) {
char c = '大';
System.out.println("\'" + c + "\'的 Unicode 编码:" + (int) c);
int num = 23398;
System.out.println("Unicode 编码为" + num + "的字符是:" + (char) num);
}
}

4. 数组

Question03

看程序输出结果,并提交结果内容或截图

1
2
3
4
5
6
7
8
9
10
11
12
public class UseIntArray {
public static void main(String[] args) {
int intArray[] = { 8, 9, 12, 13, 14 };
int sum = 0;
for (int i = 0; i < intArray.length; i++)
sum += intArray[i];
for (int i = 0; i < intArray.length; i++)
System.out.println("intArray[" + i + "]=" + intArray[i]);
System.out.println();
System.out.println("sum = " + sum);
}
}

Question04

看程序输出结果,并提交结果内容或截图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class TwoDimensionArray {
public static void main(String[] args) {
int b[][] = { { 11 }, { 21, 22 }, { 31, 32, 33 } };
int sum = 0;
b[0][0] = 1000;
for (int i = 0; i < b.length; i++) {
for (int j = 0; j < b[i].length; j++)
sum += b[i][j];
}
System.out.println("b[0][0] = " + b[0][0] + '\n' +
"sum = " + sum + '\n' +
"b.lengh = " + b.length);

int arr1[][] = new int[3][4];
int arr2[][] = new int[3][];
int arr3[][] = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 } };
int i, j, k = 0;

// arr1[][]赋值
for (i = 0; i < 3; i++) {
// arr1为3行4列
for (j = 0; j < 4; j++) {
arr1[i][j] = k++;
}
}

// arr2[][]开辟内存空间
for (i = 0; i < 3; i++) {
// arr2每一行是变长的,元素个数为3、4、5
arr2[i] = new int[i + 3];
}

// arr2[][]赋值
for (i = 0; i < 3; i++) {
for (j = 0; j < arr2[i].length; j++) {
arr2[i][j] = k++;
}
}

// 输出arr1
System.out.println(" arr1:");
for (i = 0; i < 3; i++) {
for (j = 0; j < 4; j++) {
System.out.print(" " + arr1[i][j]);
}
}
System.out.println();

// 输出arr2
System.out.println(" arr2:");
for (i = 0; i < 3; i++) {
for (j = 0; j < arr2[i].length; j++) {
System.out.println(" " + arr2[i][j]);
}
}

// 输出arr3
System.out.println(" arr3:");
for (i = 0; i < 3; i++) {
// arr3为3行3列
for (j = 0; j < 3; j++) {
System.out.print(" " + arr3[i][j]);
}
}
}
}

5. switch

Question05

阅读下面程序,给出程序的输出结果,并解释原因

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class SwitchExample {
public static void main (String[] args) {
char c = '\0';
for(int i = 1; i <= 4; i++) {
switch (i) {
case 1: c = 'J';
System.out.print(c);
case 2: c = 'e';
System.out.print(c);
break;
case 3: c = 'p';
System.out.print(c);
default: System.out.print("好");
}
}
}
}

6. 循环

Question06

实现程序输出下面这种数字方阵。

1
2
3
4
5
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

在标准输入中输入5,则输出上面这个 5×5 的方阵。如果输入7,则输出一个 7×7 的方阵。你需要提交**.java代码及运行结果截图**。任意选几个有代表性的输入即可。

Question07

实现程序输出下面这种星塔。

1
2
3
4
5
  *
***
*****
***
*

在标准输入中输入5,则输出上面这个 5 层星塔。如果输入7,则输出 7 层星塔。假设输入参数都是奇数。你需要提交**.java代码及运行结果截图**。任意选几个有代表性的输入即可。

Question08

编写静态方法 double getPi(int n),利用如下公式求圆周率的近似值。

你需要创建一个类,并添加如下方法。

1
2
3
4
5
6
7
8
/* 下面这种注释是 Java 中一种比较规范的注释,一般可以用 IDE 自动生成格式 */
/**
* 利用公式求指定精度的圆周率
* 如果 n 是负数,视其为 0
* @param n 公式中的 i 的上限
* @return 圆周率的近似值
*/
public static double getPi(int n);

你需要提交 .java 代码

题外话

  • 如果 n 是负数,视其为 0

  • 有穷求和的区间是闭区间,上限 n 对应的级数项也是要被计算的。

Question09: 快速排序

编写静态方法int[] qsort(int[] arr),需求如下

1
2
3
4
5
6
/**
* 对一个int数组快速排序,结果是升序的,并且不会开辟额外的数组空间
* @param arr 待排序的数组
* @return 升序排列好的 arr,如果 arr == null,则返回 null
*/
public static int[] qsort(int[] arr);

你需要提交 .java 代码这一次请不要使用 java.util.Array.sort() 之类的操作。

约束

  • 返回值必须是原数组,即 return arr

  • 可以任意次创建指向原数组的引用,但是请不要在排序过程中创建新的数组。

  • 可以根据需要定义新的方法。

  • 如果数组是 null,返回 null

  • 对于空数组(即 arr.length == 0),原样返回,而不是 null

Question10

现有一组数据:12, 45, 67, 89, 123, -45, 67,实现以下两步

(1) 对这组数据排序后,按照从小到大的顺序打印;

(2) 从键盘输入任意整数,判断该整数是否存在该数组中,是输出Yes,否则输出No

你需要提交**.java代码和运行结果截图**,其中第二问任意测试几个数据即可。

Question11

阅读下面代码并给出输出结果

1
2
3
4
5
6
public class ForInString {
  public static void main(String[] args) {
    for(char c : "An African Swallow".toCharArray())
      System.out.print(c + " ");
  }
}

7. 引用

Question12

阅读下面这段代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Point {
int x, y;

void setXY(int m, int n) {
x = m;
y = n;
}
}

public class Reference {
public static void main(String[] args) {
Point p1, p2;
p1 = new Point();
p2 = new Point();
System.out.println("p1 的引用: " + p1);
System.out.println("p2 的引用: " + p2);
p1.setXY(1111, 2222);
p2.setXY(-100, -200);
System.out.println("p1 的 x, y 坐标: " + p1.x + ", " + p1.y); // 1
System.out.println("p2 的 x, y 坐标: " + p2.x + ", " + p2.y); // 2
p1 = p2;
p1.setXY(0, 0);
System.out.println("p1 的引用: " + p1);
System.out.println("p2 的引用: " + p2);
System.out.println("p1 的 x, y 坐标: " + p1.x + ", " + p1.y); // 3
System.out.println("p2 的 x, y 坐标: " + p2.x + ", " + p2.y); // 4
}
}

(1) 指出代码中注释标注出的四行输出的内容会是什么。

(2) 什么是浅拷贝?什么是深拷贝?请你查阅一些资料,并给出你的资讯。

(3) 如果你要为一个类实现 copy() 方法,思考如何避免引用间赋值导致的浅拷贝?或者说,如何确保进行的是深拷贝。

(4) 解释String==equals() 的区别。

Question13

阅读下面程序,给出程序的输出结果,并解释原因

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ArrayReference {
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4 };
int[] b = { 100, 200, 300 };
System.out.println("数组 a 的元素个数 = " + a.length);
System.out.println("数组 b 的元素个数 = " + b.length);
System.out.println("数组 a 的引用 = " + a);
System.out.println("数组 b 的引用 = " + b);
a = b;
System.out.println("数组 a 的元素个数 = " + a.length);
System.out.println("数组 b 的元素个数 = " + b.length);
System.out.println("a[0] = " + a[0] + ", a[1] = " + a[1] + ", a[2] = " + a[2]);
System.out.print("b[0] = " + b[0] + ", b[1] = " + b[1] + ", b[2] = " + b[2]);
}
}

8. 可变参数

Question14

看程序输出结果,并提交结果内容或截图

1
2
3
4
5
6
7
8
9
10
11
12
13
public class VarArg {
public static void main(String[] args) {
f(1, 2);
f(-1, -2, -3, -4); // 给参数传值时,实参的个数很灵活
f(9, 7, 6);
}

public static void f(int... x) { // x是可变参数的代表,代表若干个 int 型参数
for (int i = 0; i < x.length; i++) { // x.length 是 x 代表的参数的个数
System.out.println(x[i]); // x[i] 是 x 代表的第 i 个参数(类似数组)
}
}
}

Question15

编写静态方法String strscat(String... args),需求如下

1
2
3
4
5
6
/**
* 将任意个字符串顺序连接,不应该改变任意一个原有参数
* @param args 字符串们
* @return args中的字符串顺序连接组成的新字符串
*/
public static String strscat(String... args);

样例:

调用方法 返回值
strscat("a", "b", "c", "", "e") "abce"
strscat("str") "str"

你需要提交 .java 代码文件并给出几个有代表性的测试的截图。随后回答下面几个问题:

(1) 尝试理解 Java 可变参数的实现机制,说说你的想法。

(2) 调用 strscat(new String[]{"a", "b"}) 能通过编译吗?为什么?

(3) 如果还有静态方法 String strscat(String[] args) 同时存在,代码能通过编译吗?给出 IDE 的编译结果的截图。

(4) 如果我们声明的是 String strscat(String[] args)strscat("a", "b", "c") 这样的调用还能通过编译吗?给出 IDE 的编译结果的截图。

9. 面向对象(复习并完成课堂知识点)

Question16

减肥。小王本来体重 70 kg,经过减肥,体重降到 45 kg,试从这个问题领域中识别对象、类、属性、行为、状态,和状态变化。尝试将你抽象出来的类用 Java 代码实现出来,并编写一个测试类,来描述上述过程。你需要提交 .java 代码文件。(能用代码体现你的思考即可,没有标准答案,也没有 online judge)

Question17

制作一桌丰盛的年夜饭。定义采购员类和厨师类的属性和行为,在测试类中产生采购员的对象:姑姑,妈妈和你,在测试类中产生出厨师的对象:爸爸和婶婶,协同制作年夜饭。你需要提交 .java代码文件。(能用代码体现你的思考即可,没有标准答案,也没有 online judge)