Java程序设计(2021春)——第二章课后题(选择题+编程题)答案与详解
Java程序设计(2021春)——第二章课后题(选择题+编程题)答案与详解
第二章选择题
Tip:选择题部分我只针对部分我出错的或我认为有价值的题目在此整理。
2.1 面向对象方法的特性
T1
题面
面向对象的程序设计方法采用了什么样的抽象方法构建程序的类与对象:
A 过程抽象
B 数据抽象
C 过程抽象与数据抽象
D 没有采用任何的抽象方法
答案
B
详解
面向对象程序设计方法的基本思想是使用类、对象、继承、封装和消息等概念进行程序设计。它从现实世界客观存在的事物(对象)出发来构造软件系统。强调尽可能用人类自然的思维方式思考问题,认识问题,从而将现实世界中的事物抽象成系统中的类,作为系统的基本构成单元。这样构建的系统能直接映射客观世界,更符合现实世界的本来面貌。
面向对象的基本哲学是世界是由各种各样具有自己的运动规律和内部状态的对象所组成的;不同对象之间的相互作用和通信构成了完整的现实世界。
从程序设计的角度看,面向对象的程序设计语言必须有描述对象及其相互之间的关系的语言成分。归纳起来即:系统中一切都是对象;对象是属性及其操作的封装体;对象可以按性质划分为类,对象是类的实例;实例关系和继承关系是对象之间的静态关系;消息传递是对象之间动态联系的唯一形式,也是计算的唯一形式;方法是消息的序列。
在面向对象的编程过程中,开发者要从自己的使用角度和认识角度出发来定义类,从而模拟客观世界的事物,并让自己明白这种事物是用来做什么的,对我们有什么意义。用抽象的方法忽略一个事物中与目标类无关的那些方面,充分地注意与当前目标有关的方面。
T5
题面
Java的封装性是通过什么实现的:
A 访问控制权限
B 设计内部类
C 静态域与静态方法
D 包
答案
A
详解
笔者查了一下,还没查到为什么,先mark一下。
2.2-1 类声明与对象创建
无
2.2-2 数据成员
无
2.2-3 方法成员
无
2.2-4 包
无
2.2-5类的访问控制权限
T3
题面
下列代码在编译时会发生错误,下面哪种修改可以更正错误:
class Test{
private int m;
public static void fun(){
System.out.println(m);
}
}
A 将private int m改成protected int m
B 将private int m改成public int m
C 将private int m改成static int m
D 将private int m改成int m
答案
C
详解
fun
经过了static
修饰,是类方法(静态方法),不可以调用实例变量。
2.3-1 对象初始化
无
2.3-2 内存回收
无
2.4枚举类
T2
题面
下面关于枚举类型,说法错误的是:
A 枚举值是类的对象
B 枚举中可以定义数据和方法
C 枚举类的values()方法用于获得枚举类型的枚举值的数组
D 枚举类型可以有public的构造函数
答案
D
详解
构造函数即构造方法,而枚举类型中构造方法必须是包内私有或者私有的。
第二章编程题
T1 矩阵螺旋
题面
给定m × n个元素(m行,n列)的矩阵,以螺旋顺序返回矩阵的所有元素。输入为m n以及m*n的矩阵,输出螺旋顺序的所有元素
样例输入:
3 3
1 2 3
4 5 6
7 8 9
样例输出:
123698745
样例解释:
无
思考和详解
本题笔者思考的时候说实话其实没太用到Java面向对象的特性,基本上还是按照C语言的思考方式来写的。只需要举几个例子,判断一下条件即可模拟解决本题。
具体代码
import java.util.Scanner;
public class matrix {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int m = 0;
int n = 0;
int flag = 1;
int ct = 0;
int cnt = 1;
m = in.nextInt();
n = in.nextInt();
int sum = m * n;
int[][] matrix = new int[m + 1][n + 1];
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
matrix[i][j] = in.nextInt();
}
}
in.close();
int i = 1;
int j = 1;
while ((++ct) <= sum) {
if (flag == 1) {
System.out.print(matrix[i][j++]);
if (j == n) {
flag = 2;
}
continue;
} else if (flag == 2) {
System.out.print(matrix[i++][j]);
if (i == m) {
flag = 3;
n--;
}
continue;
} else if (flag == 3) {
System.out.print(matrix[i][j--]);
if (j == cnt) {
flag = 4;
cnt++;
}
continue;
} else if (flag == 4) {
System.out.print(matrix[i--][j]);
if (i == cnt) {
flag = 1;
m--;
}
continue;
}
}
}
}
T2 组合数
题面
给定N个无重复的正整数,和目标数M,找出N中所有子集,使得每个子集的和是M,对于每个数而言,可以选多次,所有结果子集不能够重复。输入为2行,第一行为N和M,第二行为N个数,输出为总共的子集数。
样例输入:
4 7
2 3 6 7
样例输出:
2
样例解释:
7=7
2+2+3=7
思考和详解
本题使用简单递归即可,由于没有要求不重复,所以我们额外注意一下枚举的时候从当前元素开始。本题没有说明给的无重复正整数一定是按顺序给出的,但是笔者比较懒,没写sort
,但是还是过了,测试数据应该都是升序给的,不过标准来说还是应该排序一下的。
具体代码
import java.util.Scanner;
public class combination {
public static int cnt = 0;
public static int[] arr = new int[10005 + 1];
public static void func(int nowSum, int n, int ct, int target) {
if (nowSum == target) {
cnt++;
return;
} else if (nowSum > target)
return;
for (int i = ct; i <= n; i++) {
func(nowSum + arr[i], n, i, target);
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int m;
int n;
n = in.nextInt();
m = in.nextInt();
for (int i = 1; i <= n; i++) {
combination.arr[i] = in.nextInt();
}
combination.func(0, n, 1, m);
System.out.println(combination.cnt);
}
}
T3 组合数2
题面
给定N个的正整数【可能有重复】,和目标数M,找出N中所有子集,使得每个子集的和是M,对于每个数,只能选一次,所有结果子集不能够重复。输入为2行,第一行为N和M,第二行为N个数,输出为总共的子集数。
样例输入:
7 8
10 1 2 7 6 1 5
样例输出:
4
样例解释:
【1,7】
【1,2,5】
【2,6】
【1,1,6】
思考和详解
本题在本章T2的基础上略有改变,主要体现在以下两点:
- 所给数字可能有重复。
- 每个数字只能用一次,对于重复数字则是至多用所给次数次,但方案彼此不可以重复。
需要改变的地方有如下:
- 需要对数组排序,调用
java.import.Arrays
中的Arrays.sort()
方法,值得注意的是,调用该方法似乎默认对整个数组进行排序,因此建议按照正好的大小进行初始化申请空间,并从角标0存入数据。 - 需要特殊处理数组中连续的重复数字,以避免如1,1,1,1,2,2中选出了若干1,1,2这种情况。
- 需要注意不重复数字只能使用一次。
具体代码
import java.util.Arrays;
import java.util.Scanner;
class Main {
public static int cnt = 0;
public static int[] arr;
public static void func(int nowSum, int n, int ctt, int target) {
int flag;
int j = 0;
if (nowSum == target) {
Main.cnt++;
return;
} else if (nowSum > target)
return;
for (int i = ctt; i < n; i++) {
flag = 0;
if ((i + 1) < n && Main.arr[i] == Main.arr[i + 1]) {
flag = 1;
j = i;
while ((j + 1) < n && Main.arr[j] == Main.arr[j + 1]) {
j++;
}
}
if (flag == 0)
func(nowSum + arr[i], n, i + 1, target);
else {
for (int k = 1; k <= (j - i + 1); k++) {
func(nowSum + k * arr[i], n, j + 1, target);
}
i = j;
}
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int m;
int n;
n = in.nextInt();
m = in.nextInt();
Main.arr = new int[n];
for (int i = 0; i < n; i++) {
Main.arr[i] = in.nextInt();
}
in.close();
Arrays.sort(arr);
Main.func(0, n, 0, m);
System.out.println(Main.cnt);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!