博客2
第二次博客作业
题目总结
题目知识总结:
这两次题目,我们开始自己设计类与类之间的关系,运用了继承,多态,封装这三大java三大核心技术,并在写代码的时候,尽可能遵循单一职责原则(每个类只负责一部分功能,避免职责过重),里氏代换原则(子类对象可以替换掉父类对象,并且不破坏系统的正确性),开闭原则(系统对扩展开放,对修改关闭,可以通过增加新类或方法来扩展功能),合成复用原则(尽量使用组合而非继承来实现功能),依赖倒转原则(依赖于抽象,而非具体的实现).
题量大小:
题目量大小适中,简单易懂,也不像上个大作业一样,题目说明较为没明确,并不涉及算法问题.
一、类设计与继承
中等难度:需要设计多个类(如用户类、支付方式类、货物类等),并灵活应用继承关系来实现不同类型的用户、支付方式和货物。例如,用户类分为个人用户和集团用户,支付方式类分为支付宝支付、微信支付和现金支付,货物类分为普通货物、危险货物和加急货物。
设计要点:每个子类需要继承父类的共性属性和方法,并根据自身特点重写或扩展特定的方法,如用户类的折扣率计算方法、支付方式类的支付方法以及货物类的基础费率获取方法。
二、设计原则应用
较高难度:需深入理解并严格遵循单一职责原则、里氏代换原则、开闭原则、合成复用原则和依赖倒转原则等面向对象设计原则来设计类和类之间的关系。
难点解析:在设计过程中,要避免类职责过于集中或分散,确保子类对象能够正确替换父类对象且不破坏系统功能,同时要考虑系统的可扩展性,使其在需求变化时能够方便地添加新功能而不修改现有代码。例如,当新增一种支付方式时,只需添加新的支付方式类继承 Payment 类即可,无需修改其他类。
三、综合难度
整体难度属于中等偏上。它不仅要求掌握 Java 语言的基本语法和面向对象编程思想,还需要对面向对象设计原则有较好的理解和应用能力。此外,题目涉及多个类的设计和交互,需要理清类之间的关系和职责划分,逻辑较为复杂。对于初学者我们来说,可能会在类设计、设计原则应用以及程序逻辑实现等方面遇到一定的困难,需要花费较多时间进行思考和代码调试.
第一次题目
题目
题目
输入格式:
按如下顺序分别输入客户信息、货物信息、航班信息以及订单信息。
客户编号
客户姓名
客户电话
客户地址
运送货物数量
[货物编号
货物名称
货物宽度
货物长度
货物高度
货物重量
]//[]内的内容输入次数取决于“运送货物数量”,输入不包含“[]”
航班号
航班起飞机场
航班降落机场
航班日期(格式为YYYY-MM-DD)
航班最大载重量
订单编号
订单日期(格式为YYYY-MM-DD)
发件人地址
发件人姓名
发件人电话
收件人地址
收件人姓名
收件人电话
输出格式:
如果订单中货物重量超过航班剩余载重量,程序输出The flight with flight number:航班号 has exceeded its load capacity and cannot carry the order. ,程序终止运行。
如果航班载重量可以承接该订单,输出如下:
客户:姓名(电话)订单信息如下:
-----------------------------------------
航班号:
订单号:
订单日期:
发件人姓名:
发件人电话:
发件人地址:
收件人姓名:
收件人电话:
收件人地址:
订单总重量(kg):
微信支付金额:
货物明细如下:
-----------------------------------------
明细编号 货物名称 计费重量 计费费率 应交运费
1 ...
2 ...
输入样例:
10001
郭靖
13807911234
南昌航空大学
2
101
发电机
80
60
40
80
102
信号发生器
55
70
60
45
MU1234
昌北国际机场
大兴国际机场
2025-04-22
1000
900001
2025-04-22
南昌大学
洪七公
18907912325
北京大学
黄药师
13607912546
输出样例:
客户:郭靖(13807911234)订单信息如下:
-----------------------------------------
航班号:MU1234
订单号:900001
订单日期:2025-04-22
发件人姓名:洪七公
发件人电话:18907912325
发件人地址:南昌大学
收件人姓名:黄药师
收件人电话:13607912546
收件人地址:北京大学
订单总重量(kg):125.0
微信支付金额:3350.0
货物明细如下:
-----------------------------------------
明细编号 货物名称 计费重量 计费费率 应交运费
1 发电机 80.0 25.0 2000.0
2 信号发生器 45.0 30.0 1350.0
类图:
设计分析

总结分析:
该项目代码量较少(412 行),结构简单(7 个类、56 个方法),但注释严重不足(仅 0.7%),分支覆盖率低(5.2%),可能需要加强代码注释和测试覆盖。代码复杂度和嵌套深度处于合理范围,但有个别部分复杂度过高(最大复杂度 5),需重点关注优化。

代码结构与数量:
文件数量:1个文件
代码行数:412行
语句数量:250条语句
分支语句百分比:5.2%(代码中包含分支的语句占比)
方法调用语句数量:77条(代码中方法调用的次数)
带有注释的行百分比:0.7%(注释行占总代码行的比例非常低)
类和接口数量:7个(项目中定义的类和接口总数)
每类方法数:平均每个类有8个方法
平均每方法语句数:3.96条语句(每个方法平均包含的语句数量)
复杂度与嵌套:
最复杂方法的行号:未定义(可能表示没有特别复杂的单个方法,或者未记录)
最复杂方法名称:Order.Rare()(复杂度最高的方法)
最大复杂度:5(代码中复杂度最高的部分)
基线图(Kiviat Graph):显示了多个指标的综合表现,包括注释百分比、平均每类方法数、复杂度、深度等。
柱状图(Block Histogram):显示了不同嵌套深度下的语句分布情况,表明大部分语句的嵌套深度较低,但存在一些深度较高的语句。
总结与改进方向
代码注释不足:只有0.7%的代码行包含注释,严重影响代码的可读性和维护性,需要增加注释。
分支覆盖率低:分支语句的覆盖率仅为5.2%,表明测试覆盖不足或分支逻辑较少,需加强测试。
复杂度管理:尽管整体复杂度较低(平均复杂度1.33),但存在一个复杂度高的方法(Order.Rare(),复杂度5),需要优化以降低复杂度。
嵌套深度合理:平均嵌套深度为1.54,整体嵌套情况尚可,但有个别语句嵌套深度较高,需关注代码结构优化。

方法度量分析
- 复杂度(Complexity)
复杂度是衡量代码中路径数量的指标,通常与代码的复杂性和可维护性相关。
高复杂度方法:
Cargocompany.display():复杂度为4,是复杂度最高的方法之一。
Main.main():复杂度为3。
Order.Rare():复杂度为5,是复杂度最高的方法。
复杂度过高的方法可能导致维护困难,建议进行代码重构。 - 语句数量(Statements)
语句数量是方法中包含的语句总数。
语句较多的方法:
Main.main():包含57条语句,是语句最多的方法,表明该项目的主要逻辑集中在此。
Cargocompany.display():包含17条语句。
Order.Rare():包含9条语句。
语句过多的方法可能难以理解和维护,建议拆分。 - 最大嵌套深度(Maximum Depth)
嵌套深度是方法中嵌套结构(如if-else、循环等)的最大层数。
高嵌套深度方法:
Main.main():最大嵌套深度为3。
Cargocompany.display():最大嵌套深度为4。
Order.Rare():最大嵌套深度为3。
嵌套过深的方法可能影响可读性,建议减少嵌套层次。 - 调用次数(Calls)
调用次数是方法中调用其他方法的次数。
高调用次数方法:
Cargocompany.display():调用26次。
Main.main():调用32次。
高调用次数的方法可能是核心逻辑的集中体现,需关注其性能。

类别总结
Cargocompany 类:
包含多个简单方法(getFlight(), setFlight(), setOrder()),复杂度较低(1)。
display() 方法复杂度较高(4),语句较多(17),嵌套深度(4),调用次数(26)较多。
Main 类:
main() 方法是程序入口,复杂度为3,包含57条语句,嵌套深度为3,调用次数为32次。
Order 类:
包含多个getter和setter方法,复杂度较低(1)。
Rare() 方法复杂度为5,语句为9,嵌套深度为3,调用次数为3次。
Flight 和 Dispatcher 类:
包含多个简单方法,复杂度较低(1),嵌套深度为2。
其他类:
类似于上述类,方法复杂度普遍较低。
改进建议
降低复杂度:对复杂度过高的方法(如 Order.Rare() 和 Cargocompany.display())进行重构,分解为更小的逻辑单元。
减少嵌套深度:优化嵌套逻辑,使用更清晰的代码结构。
增加注释:当前注释比例仅为0.7%,需要大量增加注释以提高代码可读性和可维护性。
测试覆盖:分支语句百分比为5.2%,需增加测试用例以提高覆盖。
指标的分析
平均复杂度(Avg Complexity):1.33,处于参考范围2.0-4.0之间,表明代码复杂度较低,整体可维护性较好。
注释比例(% Comments):0.7%,远低于参考范围8%-20%,显示代码注释严重不足,需要大量增加注释以提高可读性。
平均每类方法数(Methods/Class):8.00,处于参考范围4-16之间,显示类的设计合理,方法分配均匀。
平均每方法语句数(Avg Stmts/Method):3.96,处于参考范围6-12之间,表明方法的长度适中,逻辑不会过于复杂。
最大嵌套深度(Max Depth):4,处于参考范围3-7之间,可以接受,但部分代码可能嵌套较深,需关注。
最大复杂度(Max Complexity):5,处于参考范围2-8之间,表明复杂度最高的部分尚在合理范围内,但仍需优化以降低潜在风险。
平均嵌套深度(Avg Depth):1.54,处于参考范围1.0-2.2之间,显示嵌套深度总体较低,代码结构较为清晰。
第二次题目
题目
输入格式:
按如下顺序分别输入客户信息、货物信息、航班信息以及订单信息。
客户类型[可输入项:Individual/Corporate]
客户编号
客户姓名
客户电话
客户地址
货物类型[可输入项:Normal/Expedite/Dangerous]
运送货物数量
[货物编号
货物名称
货物宽度
货物长度
货物高度
货物重量
]//[]内的内容输入次数取决于“运送货物数量”,输入不包含“[]”
航班号
航班起飞机场
航班降落机场
航班日期(格式为YYYY-MM-DD)
航班最大载重量
订单编号
订单日期(格式为YYYY-MM-DD)
发件人地址
发件人姓名
发件人电话
收件人地址
收件人姓名
收件人电话
支付方式[可输入项:Wechat/ALiPay/Cash]
输出格式:
如果订单中货物重量超过航班剩余载重量,程序输出The flight with flight number:航班号 has exceeded its load capacity and cannot carry the order. ,程序终止运行。
如果航班载重量可以承接该订单,输出如下:
客户:姓名(电话)订单信息如下:
-----------------------------------------
航班号:
订单号:
订单日期:
发件人姓名:
发件人电话:
发件人地址:
收件人姓名:
收件人电话:
收件人地址:
订单总重量(kg):
[微信/支付宝/现金]支付金额:
货物明细如下:
-----------------------------------------
明细编号 货物名称 计费重量 计费费率 应交运费
1 ...
2 ...
输入样例:
在这里给出一组输入。例如:
Corporate
10001
郭靖
13807911234
南昌航空大学
Expedite
2
101
发电机
80
60
40
80
102
信号发生器
55
70
60
45
MU1234
昌北国际机场
大兴国际机场
2025-04-22
1000
900001
2025-04-22
南昌大学
洪七公
18907912325
北京大学
黄药师
13607912546
ALiPay
输出样例:
在这里给出相应的输出。例如:
客户:郭靖(13807911234)订单信息如下:
-----------------------------------------
航班号:MU1234
订单号:900001
订单日期:2025-04-22
发件人姓名:洪七公
发件人电话:18907912325
发件人地址:南昌大学
收件人姓名:黄药师
收件人电话:13607912546
收件人地址:北京大学
订单总重量(kg):125.0
支付宝支付金额:4360.0
货物明细如下:
-----------------------------------------
明细编号 货物名称 计费重量 计费费率 应交运费
1 发电机 80.0 40.0 3200.0
2 信号发生器 45.0 50.0 2250.0
类图:
设计分析

总结
该项目代码量较少(483 行),结构简单(7 个类),但注释严重不足(仅 0.6%),分支覆盖率低(10.3%),可能需要加强代码注释和测试覆盖。代码复杂度和嵌套深度处于合理范围,但有个别部分复杂度过高(最大复杂度 14),需重点关注优化。

代码结构与数量
文件数量:1个文件
代码行数:483行
语句数量:290条语句
分支语句百分比:10.3%(代码中包含分支的语句占比)
方法调用语句数量:84条(代码中方法调用的次数)
带有注释的行百分比:0.6%(注释行占总代码行的比例非常低)
类和接口数量:7个(项目中定义的类和接口总数)
每类方法数:平均每个类有8.43个方法
平均每方法语句数:4.42条语句(每个方法平均包含的语句数量)
复杂度与嵌套
最复杂方法的行号:未定义(可能表示没有特别复杂的单个方法,或者未记录)
最复杂方法名称:Order.Rare()(复杂度最高的方法)
最大复杂度:14(代码中复杂度最高的部分)
基线图(Kiviat Graph)显示了多个指标的综合表现,包括注释百分比、平均每类方法数、复杂度、深度等。
柱状图(Block Histogram)显示了不同嵌套深度下的语句分布情况,表明大部分语句的嵌套深度较低,但存在一些深度较高的语句。
总结与改进方向
代码注释不足:只有0.6%的代码行包含注释,严重影响代码的可读性和维护性,需要增加注释。
分支覆盖率低:分支语句的覆盖率仅为10.3%,表明测试覆盖不足或分支逻辑较少,需加强测试。
复杂度管理:尽管整体复杂度较低(平均复杂度1.65),但存在一个复杂度高的方法(Order.Rare(),复杂度14),需要优化以降低复杂度。
嵌套深度合理:平均嵌套深度为1.78,整体嵌套情况尚可,但有个别语句嵌套深度较高,需关注代码结构优化。

复杂度分布
复杂度较高的方法:Order.Rare() 方法复杂度高达14,表明其逻辑较为复杂,可能是由于包含多个条件判断或循环嵌套。这会增加代码的维护难度和出错风险,建议对其进行重构,分解为多个 simpler 方法。
中等复杂度方法:如Main.main()(复杂度3)、Order.allmoney()(复杂度4)和Cargocompany.display()(复杂度4),这些方法有一定的复杂性,需要关注其可读性和可维护性。
低复杂度方法:大部分方法复杂度为1或2,表明这些方法逻辑简单,符合良好的编程实践。
语句数量
语句较多的方法:Main.main() 包含63条语句,是语句最多的方法,表明该项目的主要逻辑集中在此。 Order.Rare() 包含31条语句,较多的语句数量可能意味着方法过长,建议拆分。
语句适中的方法:如Cargocompany.display() 包含17条语句,Order.weight() 包含5条语句。
语句较少的方法:大部分 getter 和 setter 方法仅包含1或2条语句,简洁明了。
嵌套深度
嵌套深度较深的方法:Order.Rare() 的最大嵌套深度为5,表明存在较为复杂的嵌套逻辑,可能影响代码的可读性。
嵌套深度适中的方法:如Main.main() 和 Order.allmoney() 的最大嵌套深度为3。
嵌套深度较浅的方法:大部分方法的最大嵌套深度为2,表明代码结构较为清晰。
调用次数
调用次数较多的方法:Cargocompany.display() 被调用26次,Main.main() 被调用35次,表明这些方法是项目中的核心方法,频繁的调用可能意味着它们是业务逻辑的关键部分。
调用次数适中的方法:如Order.allmoney() 被调用2次,Order.weight() 被调用5次。
调用次数较少的方法:大部分方法的调用次数为0或1,表明这些方法可能是辅助方法或尚未被充分使用。
注释不足
注释比例低:仅有0.6%的代码行包含注释,这将严重影响代码的可读性和可维护性,建议在后续开发中增加注释,尤其是对复杂度高的方法和核心逻辑部分进行详细注释。
改进建议
重构复杂方法:对复杂度高的方法(如Order.Rare())进行重构,降低其复杂度和嵌套深度。
增加注释:提高代码的注释比例,尤其是对复杂逻辑和核心方法进行详细说明。
优化方法长度:对语句数量较多的方法进行拆分,使其更简洁明了。
加强测试:提高分支覆盖率,确保代码的稳定性和可靠性。

度量指标及值
平均复杂度(Avg Complexity):1.65,低于2.0-4.0的理想范围,表明代码整体复杂度较低,易于理解和维护。
注释百分比(% Comments):0.6%,远低于8-20%的理想范围,注释不足,可能影响代码的可读性。
每类方法数(Methods/Class):8.43,处于4-16的理想范围内,表明类的设计较为合理。
平均每方法语句数(Avg Stmts/Method):4.42,处于6-12的理想范围内,表明方法的长度适中。
平均深度(Avg Depth):1.78,处于1.0-2.2的理想范围内,表明代码的嵌套深度较为合理。
最大深度(Max Depth):5,处于3-7的理想范围内,尽管在可接受范围内,但有些代码的嵌套深度较大,可能影响可读性。
最大复杂度(Max Complexity):14,高于2-8的理想范围,表明存在一些复杂度较高的代码部分,需要优化。
总结与改进方向
注释不足:需要增加注释,特别是对复杂度较高的部分进行详细说明,以提高代码的可读性和可维护性。
复杂度管理:尽管整体复杂度较低,但存在一些复杂度较高的代码部分(如最大复杂度为14),需要进行重构和优化,以降低维护难度。
嵌套深度:大部分代码的嵌套深度较为合理,但需要关注那些嵌套深度较大的部分,优化代码结构,提高可读性。
题目踩坑心得
第一次题目
这是我第一次的提交记录:

对于第一次写题目的时候我运行的结果是

我发现下面的货物明细格式似乎不正确:后面我经过检查,我询问了别人的这个问题,他的解释是,我们应该使用制表符,来进行打印,且我相对正确答案漏掉一部分:订单重质量和微信支付金额.
经过第二次的修改我得到了这个:

我当时的这一部分的输出是
System.out.printf("订单总重量(kg):%.1f\n",(double)allweight);
System.out.printf("微信支付金额:%.1f\n",(double)allmoney);
public double allmoney()
{
for (Goods good : goods) {
allmoney+=money(good);
}
return allmoney;
}
public double allweight(){
for (Goods good : goods) {
allweight+=weight(good);
}
return allweight;
}
我并没有调用这两个方法,来修改allweight和allmoney,因此,我在main方法里面调用了这个两个方法,使得这个问题得以解决.
第二次题目
第一次提交记录是这个:

而我的出的结果是:
客户:郭靖(13807911234)订单信息如下:
-----------------------------------------
航班号:MU1234
订单号:900001
订单日期:2025-04-22
发件人姓名:洪七公
发件人电话:18907912325
发件人地址:南昌大学
收件人姓名:黄药师
收件人电话:13607912546
收件人地址:北京大学
订单总重量(kg):125.0
现金支付金额:4360.0
货物明细如下:
-----------------------------------------
明细编号 货物名称 计费重量 计费费率 应交运费
1 发电机 80.0 40.0 3200.0
2 信号发生器 45.0 50.0 2250.0
运行结果基本和答案一样,我首先处理了异常测试把代码改成:
System.out.println("The flight with flight number:" +flightnum+" has exceeded its load capacity and cannot carry the order.");
后面经过我不断反测试用例我发现:我没有注意这里面字符方式是可以指定的,
我把代码改成
public String getPayment() {
if ("ALiPay"==payment) {
return "支付宝";
} else if ("Wechat"==payment) {
return "微信";
} else {
return "现金";
}
但依旧是错误,我又想到"=="是判断这两个对象是否是同一个对象,我对这个进行修改成:
public String getPayment() {
if ("ALiPay".equals(payment)) {
return "支付宝";
} else if ("Wechat".equals(payment)) {
return "微信";
} else {
return "现金";
}
知识收获
面向对象编程的核心技术:
继承:学会了如何通过继承实现代码复用,例如用户类(个人用户和集团用户)、支付方式类(支付宝、微信、现金)和货物类(普通货物、危险货物、加急货物)的设计。
多态:理解了多态的实现方式,特别是子类对象可以替换父类对象的特性,例如在计算折扣率和支付方式时,子类可以覆盖父类的方法。
封装:学会了如何将数据和方法封装在类中,隐藏内部实现细节,只暴露必要的接口,例如货物类的计费重量和基础费率的计算。
设计原则的应用:
单一职责原则:学会了如何将每个类的功能划分得更清晰,避免一个类承担过多职责。例如,订单类只负责订单信息的管理,而运费计算则由专门的运费计算类负责。
里氏代换原则:理解了子类对象必须能够替换掉父类对象,并且不破坏系统的正确性。在实际代码中,通过合理设计子类的方法,确保了这一点。
开闭原则:学会了如何设计系统使其对扩展开放,对修改关闭。例如,新增一种支付方式时,只需添加新的支付方式类,而无需修改现有代码。
合成复用原则:学会了尽量使用组合而非继承来实现功能,例如订单类中包含多个货物对象,而不是通过继承来实现。
依赖倒转原则:理解了依赖于抽象而非具体实现的重要性,例如支付方式类依赖于一个抽象的支付接口,而不是具体的支付实现。
代码结构与质量:
学会了如何通过类图来设计系统结构,明确了类之间的关系和职责划分。
理解了代码复杂度、嵌套深度等指标对代码可读性和可维护性的影响。
需要进一步学习及研究的地方:
代码注释与文档:注释严重不足,只有0.6%-0.7%的代码行包含注释,这严重影响了代码的可读性和维护性。需要学习如何编写高质量的注释,特别是对复杂逻辑和核心方法进行详细说明。需要学习如何编写更详细的文档,包括类的功能、方法的参数和返回值等。
测试覆盖: 分支覆盖率低,分别为5.2%和10.3%,表明测试覆盖不足。需要学习如何编写更全面的测试用例,确保代码的稳定性和可靠性。
需要学习如何使用自动化测试工具,提高测试效率。
复杂度管理:
存在复杂度过高的方法(如Order.Rare(),复杂度为5和14),需要学习如何对复杂方法进行重构,分解为更小的逻辑单元。
需要学习如何优化嵌套逻辑,减少嵌套深度,提高代码的可读性。
设计模式的深入应用:
需要进一步学习和实践更多设计模式,如工厂模式、策略模式等,以更好地解决实际问题。
课程改进建议
增加实践案例:
教师可以提供更多实际的项目案例和自动化测试工具,帮助我们更好地理解面向对象设计原则和设计模式的应用和掌握测试技能,提高代码质量。
作业与实验:
提供参考代码,在一些复杂的作业中,初学者并不能很好的运用几个原则,写完代码后,提供部分参考代码或框架,帮助我们更好地理解和实现任务。

浙公网安备 33010602011771号