第一次迭代作用总结总结

前言
第一次迭代专业完成,主要围绕着类的设计进行出题迭代,不断增加新功能,通过迭代作业,我学会了一下知识点
1,熟悉了java的基本输入输出
2,熟悉了java里Alist工具的应用
3,复习了冒泡排序法和选择排序法
4,掌握了类的封装的应用及类的封装的基本原则
5,掌握了4种类间关系和如何设计类间关系
本次的题目题目量不大,难度呈现简单-->一般-->难的迭代趋势,以下是题目原题,源码实现,源码分析,相应类图,相应的解释和心得
第一次作业
作业要求
【作业背景】
在航空业中,航班起飞前需要进行严格的“配载”,即计算飞机的旅客、货物、行李的重量分布,计算出飞机的重心位置,以确保飞行安全。本系列作业将围绕这一真实场景展开。
【本次作业需求说明】
设计一个基础的航班货运配载模块。系统需要记录航班的基本信息(航班号、最大起飞重量、最大业载重量)。地勤人员可以按照货物重量从高到低向该航班添加货物(货物名称、重量)。系统需要实时计算当前已装载的总重量,并判断是否超载。
【设计要求】
类设计必须符合单一职责原则(SRP),参考类图如下所示(仅作参考,可自行加工具类)。
第1行:输入航班号flightNo(字符串,例如CA1201)
第2行:输入该航班最大载重重量maxWeight(实型数,例如1200.0)
第3行:输入该航班要装载的货物件数n(整型数,例如10)
从第4行开始,循环输入要装载的货物的名称cargoName(字符串)和cargoWeight重量(实型数)
提示:在使用Scanner输入的时候,nextLine()方法会接受上一次输入的回车符号,因此,建议大家在nextLine()之前再加一个nextLine(),如下代码所示:
前n行按照装载顺序依次输出货物的信息,格式如下:
货物[名称 重量:重量值kg]
第n+1行输出装载的总重量以及该航班最大载重量,格式如下:
总重量: 重量值kg / 最大载重: 载重值kg
最后一行输出配载状态,如果没有超载,则输出配载状态:正常,如果超载则输出警告:严重超载
注意:输出的数值均保留1位小数。
实现方式
程序包含5个主要类,形成一个完整的数据流:
Main → Flight → Loadmanifest → CargoSorter → Cargo
核心类解析

  1. Cargo(货物类)
    属性:
    cargoName:货物名称
    cargoWeight:货物重量(kg)
    方法:
    构造方法:初始化货物信息
    getName():获取货物名
    getWeight():获取货物重量
  2. CargoSorter(排序器类)
    核心方法:CargoSort(Cargo[] cargos)
    排序算法:使用冒泡排序(Bubble Sort)
    排序规则:按重量从大到小降序排列
    时间复杂度:O(n²)
  3. Loadmanifest(装载清单类)
    属性:
    cargo[]:货物数组
    maxWeight:最大载重量
    核心功能:
    initCargos():初始化并排序货物
    Printcargos():格式化打印所有货物
    totalWeight():计算货物总重量
    StatusFlight():检查并显示装载状态
  4. Flight(航班类)
    属性:
    flightNo:航班号
    loadManifest:装载清单对象
    作为系统的入口点,关联航班与装载清单
    数据处理流程
    输入顺序:
  5. 航班号
  6. 最大载重量
  7. 货物数量
  8. 货物信息(名称 + 重量,重复n次)
    处理过程:
    java
    1 创建货物数组
    Cargo[] cargos = new Cargo[n];
  9. 排序货物(按重量降序)
    sorter.CargoSort(cargos);
  10. 创建装载清单
    Loadmanifest loadManifest = new Loadmanifest(maxWeight);
  11. 关联航班
    Flight flight = new Flight(loadManifest, flightNo);
  12. 输出结果
    flight.loadManifest.Printcargos();
    flight.loadManifest.StatusFlight();
    超载检查逻辑
    程序通过比较实际总重量与最大载重量判断状态:
    java
    if (total <= maxWeight)
    System.out.println("配载状态:正常");
    else
    System.out.println("警告:严重超载");

类图如下
image

Bug分析如下
image
问题 1:分支覆盖率极低(16.7%)→ 测试不充分
代码中包含多个 if条件判断,但测试只覆盖了其中一小部分:
🔍 代码中关键分支点:
if (cargos[j].getWeight() < cargos[j + 1].getWeight())
→ 排序算法中的比较分支,必须被覆盖,否则排序逻辑未被验证。
if (total <= maxWeight)
→ 在 StatusFlight()中判断是否超载,这是核心业务逻辑,必须测试“正常”和“超载”两种情况。
sc.nextLine()和 sc.nextDouble()的混合使用
→ 可能存在输入缓冲区问题,但测试中是否覆盖了异常输入?(报告中未体现异常路径) 结论:测试只覆盖了极少量分支(比如只测了“正常载重”或“排序未发生交换”),导致分支覆盖率只有 16.7%。

问题 2:语句覆盖率约 40%(42/104)→ 大量代码未执行
总行数 104,语句数 42(注意:语句 ≠ 行,一行可能有多条语句)。
但实际执行的语句只有 42 条,意味着:
CargoSorter.CargoSort()中可能没有完全执行内层循环(比如 n=1 时内层不执行);
Loadmanifest.Printcargos()和 totalWeight()可能只在特定数据下执行;
Flight类几乎没有被测试(构造函数、字段赋值);
main()方法中 Scanner的输入流程可能只在一种输入下测试。
结论:测试用例太单一,没有覆盖各种边界情况(如空数组、超重、单件货物等)。

问题 3:类名和方法命名不规范 → 可维护性差
CargoSorter中的方法叫 CargoSort(首字母大写)→ 应该是 cargoSort(驼峰命名,方法小写开头)。
Loadmanifest.Printcargos()→ 应为 printCargos()。
Flight.loadManifest是 public → 破坏封装,应通过 getter 访问。
虽然不是覆盖率问题,但会影响后续测试和重构。

第二次迭代作业
作业要求
【作业背景】
在第一次作业的基础上,航空公司要求进一步细化配载管理。飞机不再只有一个货舱,而是分为多个货舱(如前舱、后舱等)。每个货舱有独立的最大载重和固定数量的装载位置(行列网格)。地勤人员需要按照货物重量从高到低的顺序,将每件货物选择放入某个货舱,系统需实时检查该货舱是否超载。同时,系统需要记录航班整体的最大起飞重量和最大业载重量,并判断整体是否超载。
【本次作业需求说明】
设计一个扩展的航班货运配载模块,实现以下功能:
航班信息管理:记录航班号、最大起飞重量、最大业载重量。
货舱管理:
每个货舱有唯一标识(如“前舱”)、最大载重、行数、列数(组成位置网格)。
货舱与其位置是组合关系(CargoCompartment 创建时内部生成 Position 列表)。
货舱与装载的货物是聚合关系(Cargo 可独立存在)。
货物装载:
输入所有待装载货物(名称、重量、目标货舱ID)。
系统先按货物重量从高到低排序,再依次尝试将货物装入指定的货舱。
如果目标货舱的当前重量 + 该货物重量 ≤ 该货舱最大载重,则装载成功,否则装载失败并给出提示。
输出要求:
按排序后的顺序输出每件货物的装载结果(成功或失败)。
输出每个货舱的已装载总重量及状态(是否超载)。
输出航班整体总重量及与最大起飞重量、最大业载重量的对比,判断整体是否超载。
【设计要求】
必须严格遵循单一职责原则(SRP),不得将多个职责合并到一个类中。违背 SRP 本题不得分。
必须实现以下类(参考提供的类图与代码框架):
Position:表示货舱中的一个位置(行、列),提供 getPosName() 等方法。
Cargo:表示货物,包含 id(货物名称)、weight。
CargoCompartment:货舱类,包含 id、maxWeight、positions(组合)、cargos(聚合),提供 addCargo(Cargo cargo)、getCurrentWeight() 等方法。
Flight:航班类,包含航班号、最大起飞重量、最大业载重量、List。
LoadDispatcher:调度类,负责对货物列表按重量降序排序(sortCargos)、查找货物(FindCargo)。
InputValidator:输入校验类,提供整数、浮点数的范围校验方法。
输入格式:
第1行:航班号(字符串)
第2行:最大起飞重量(实型)
第3行:最大业载重量(实型)
第4行:货舱数量 m(整数,1 ≤ m ≤ 5)
接下来 m 行,每行描述一个货舱:货舱ID(字符串) 最大载重(实型) 行数(整数) 列数(整数)
接下来一行:货物件数 n(整数,1 ≤ n ≤ 100)
接下来 n 行,每行描述一件货物:货物名称(字符串) 重量(实型) 目标货舱ID(字符串,必须与上面输入的某个货舱ID一致)。
例如:
CA1201
20000
15000
2
前舱 5000 2 5
后舱 8000 3 5
3
电子产品 850 前舱
水果 500 后舱
体育用品 128 前舱
输出格式:
1.首先输出一行:===== 货物按重量降序排序后装载结果 =====
2.接下来 n 行,按排序后的顺序输出每件货物的装载信息,同等重量的货物按输入的先后顺序排列,格式如下:
装载成功:货物[名称 重量:重量值kg] → 装入货舱[货舱ID] 成功
装载失败:货物[名称 重量:重量值kg] → 装入货舱[货舱ID] 失败 (超载)
3.然后输出一行空行(可选,便于阅读)
4.按输入顺序依次输出每个货舱的统计信息,格式:
货舱[货舱ID] 已装重量: 重量值kg / 最大载重: 载重值kg → 状态: 正常/超载
5.输出航班整体信息:
航班总重量: 总重量值kg / 最大起飞重量: 起飞重量值kg / 最大业载: 业载值kg
6.最后一行输出整体配载状态,可能为:
整体配载状态:正常
警告:超过最大起飞重量
警告:超过最大业载重量
警告:超过最大起飞重量和最大业载重量
注:所有重量数值保留1位小数。
例如:
===== 货物按重量降序排序后装载结果 =====
货物[电子产品 重量:850.0kg] → 装入货舱[前舱] 成功
货物[水果 重量:500.0kg] → 装入货舱[后舱] 成功
货物[体育用品 重量:128.0kg] → 装入货舱[前舱] 成功
货舱[前舱] 已装重量: 978.0kg / 最大载重: 5000.0kg → 状态: 正常
货舱[后舱] 已装重量: 500.0kg / 最大载重: 8000.0kg → 状态: 正常
航班总重量: 1478.0kg / 最大起飞重量: 20000.0kg / 最大业载: 15000.0kg
整体配载状态:正常
实现方法
程序结构
程序包含6个主要类,形成复杂的数据管理系统:
Main → Flight → LoadDispatcher → CargoCompartment → Cargo → Position
核心类详细解析
1.Position(位置类)
属性:
row:行号
col:列号
功能:
表示货舱中的具体位置坐标
为货舱网格化管理提供基础
支持二维空间布局管理
2. Cargo(货物类)- 增强版
属性:
id:货物编号
weight:货物重量
destination:目标货舱ID
方法:
构造方法
getter方法:getId(), getWeight(), getDestination()
新增功能:
增加了目的地属性,支持货舱定向装载
为智能分配提供数据基础
支持货物与货舱的关联关系
3. CargoCompartment(货舱类)- 核心管理单元
属性:
id:货舱标识
maxWeight:最大载重量
rowNumber:行数
colNumber:列数
positionlist:位置列表
cargolist:货物列表
static count:静态计数器
核心功能:
网格化位置管理
动态货物装载
实时重量监控
容量管理
位置初始化
主要方法:
InitPositionList():初始化网格位置
addCargo(Cargo cargo):添加货物
getCurrentWeight():计算当前重量
getter方法:getId(), getMaxWeight()
4. Flight(航班类)- 增强版
属性:
flightNo:航班号
maxFlyWeight:最大起飞重量
maxLoadWeight:最大业载重量
cargoCompartment:货舱数组
新增功能:
支持多个货舱管理
双重量限制(起飞重量+业载重量)
货舱查找功能
航班与货舱的关联管理
主要方法:
构造方法:支持多个货舱初始化
getCargoCompartments():获取所有货舱
getCargoCompartmentById(String id):按ID查找货舱
getter方法:getMaxFlyWeight(), getMaxLoadWeight()
5. LoadDispatcher(装载调度类)
功能:
货物排序调度
使用选择排序算法
按重量降序排列
核心方法:
sortCargos(List cargolist):对货物列表进行排序
采用选择排序,时间复杂度O(n²)
排序规则:重量从大到小
6. Main
主要功能:
用户输入处理
数据初始化
业务流程控制
结果输出显示
系统特性

  1. 多层次重量限制
    货舱级限制:每个货舱有独立的最大载重
    航班级限制:分为最大起飞重量和最大业载重量
    双重检查机制:局部和全局的重量验证
  2. 智能装载策略
    按重量降序装载:优先装载重货
    目的地匹配:货物装入指定货舱
    容量检查:实时检查货舱剩余容量
    失败处理:装载失败有明确提示
  3. 网格化管理
    货舱采用行列网格布局
    支持位置坐标管理
    为扩展货位管理预留接口
    数据处理流程
  4. 输入处理阶段
    输入顺序:
  5. 航班号2. 最大起飞重量3. 最大业载重量4. 货舱数量m5. 货舱信息(重复m行,每行:ID 最大重量 行数 列数)6. 货物数量n7. 货物信息(重复n行,每行:ID 重量 目标货舱)
    输入特点:
    支持多货舱配置
    货物指定目标货舱
    货舱有空间维度(行列)
  6. 数据初始化阶段
    创建航班对象
    初始化货舱数组
    货物列表初始化
    货舱位置网格初始化
  7. 排序处理阶段
    使用LoadDispatcher对货物排序
    按重量从大到小降序排列
    准备装载序列
  8. 装载执行阶段
    装载逻辑:
    按排序顺序遍历货物
    根据货物destination查找目标货舱
    检查货舱剩余容量
    成功则装入,失败则记录
    更新货舱当前重量
    检查条件:
    if (目标货舱.当前重量 + 货物重量 ≤ 货舱.最大载重) { 装入成功
    } else {
    装入失败
    }
  9. 结果输出阶段
    输出内容:
    装载过程记录
    各货舱状态
    航班总体状态
    装载结果汇总

状态检查机制

  1. 三层检查体系
    第一层 - 货舱级检查:
    货舱状态 = (当前重量 > 最大载重) ? "超载" : "正常"
    第二层 - 航班级检查:
    检查1:总重量 ≤ 最大起飞重量?
    检查2:总重量 ≤ 最大业载重量?
    第三层 - 综合状态判断:
    if (检查1通过 && 检查2通过) → "整体配载状态:正常"
    else if (检查1通过 && 检查2失败) → "警告:超过最大业载重量"
    else if (检查1失败 && 检查2通过) → "警告:超过最大起飞重量"
    else → "警告:超过最大起飞重量和最大业载重量"
    输出格式说明
  2. 装载过程输出
    货物[货物ID 重量:X.Xkg] → 装入货舱[货舱ID] 成功/失败
  3. 货舱状态输出
    货舱[货舱ID] 已装重量: X.Xkg / 最大载重: X.Xkg → 状态: 正常/超载
  4. 航班总体输出
    航班总重量: X.Xkg / 最大起飞重量: X.Xkg / 最大业载: X.Xkg
    整体配载状态:[状态描述]

类图如下
image

Bug分析如下
image

  1. 分支覆盖率仅 16.7% → 测试严重不足
    代码中大量 if分支未被覆盖:
    if(parts.length<4)→ 处理输入行不足的情况,测试是否覆盖了这种异常输入?
    if(compartment.getId().equals(id))→ 查找货舱匹配,是否测试了找不到货舱的情况(返回 null)?
    if(maxIndex!=i)→ 排序交换逻辑,是否测试了已排序、未排序的情况?
    if(cargolist.get(j).getWeight() > ...)→ 排序比较,是否测试了相等重量的情况?
    这些分支在报告中未被覆盖,导致覆盖率极低。
  2. 语句覆盖率约 40%(42/104)→ 大量代码未执行
    总行数 104,语句数 42(注意:语句 ≠ 行),说明:
    CargoCompartment.InitPositionList()→ 初始化位置列表,测试是否调用了这个方法?
    addCargo(Cargo cargo)→ 添加货物,是否在测试中调用?
    getCurrentWeight()→ 计算当前重量,是否测试了空列表、单元素、多元素?
    sortCargos()→ 排序算法,是否测试了 n=0、n=1、n>1 的情况?
    这些方法在测试中未被充分调用,导致语句覆盖低。
  3. 命名不规范 + 代码可读性差
    Lo截断 → 应该是 LoadDispatcher.loadCargo(...),但未完成;
    变量名如 cargolist、positionlist→ 建议用 cargoList、positionList;
    方法名 InitPositionList→ 应该是 initPositionList(驼峰命名);
    类中方法如 getId()、getWeight()等命名规范,但部分方法如 addCargo未在 main中被调用(测试未覆盖)。

第三次迭代作业
作业要求
题目:航空器配载与货运管理系统——配平计算
在前两次作业中,我们实现了基础的货运管理和多货舱的划分,并引入了算法工具类。但在真实的航空业务中,飞机的装载不仅包含货物,还包含旅客及其随身行李。更关键的是,任何装载都必须经过严格的“载重平衡”计算,得出飞机的重心位置,以确保飞行安全。
【问题背景】
在航空器配载中,所有装载项(旅客、前舱货物、后舱货物)都有其对应的力臂。重量乘以力臂等于力矩。所有力矩之和除以总重量,即为飞机的实际重心。为了统一标准,实际重心需要换算为占平均空气动力弦(MAC)的百分比。
【题目说明】
1.系统预设常量(需在计算类中定义为静态常量)
基准数据:空机重量 40,000.0 kg,空机重心力臂 16.25 m。
力臂参数:
旅客舱平均力臂:18.0 m
前货舱力臂:12.0 m (根据货舱ID值为1判断)
后货舱力臂:22.0 m (根据货舱ID值为2判断)
MAC参数:MAC长度 5.0 m,MAC前缘距基准距离 15.0 m。
安全范围:CG% 在 25.0% 到 38.0% 之间为安全。
计算步骤与公式
第一步:计算旅客总重量及力矩
旅客总重量 = Σ (单名旅客总重) (注:单名旅客总重 = 75.0kg + 其行李重量)
旅客总力矩 = 旅客总重量 × 旅客舱力臂
第二步:计算各货舱总重量及力矩
遍历航班的所有 CargoCompartment,累加每个舱的当前货物重量。
货舱总力矩 = Σ (某货舱当前重量 × 该货舱对应力臂)
第三步:计算全机总重量与总力矩
全机总重量 = 空机重量 + 旅客总重量 + 所有货舱总重量
全机总力矩 = (空机重量 × 空机力臂) + 旅客总力矩 + 货舱总力矩
第四步:计算实际重心
实际重心 = 全机总力矩 / 全机总重量
第五步:换算重心百分比 (CG% MAC) 并评估
CG% MAC = ( (实际重心 - MAC前缘距离) / MAC长度 ) × 100%
判断:如果 25.0 <= CG% MAC <= 38.0,评估结果为“安全(GREEN)”,否则为“危险(RED - 超出极限重心范围)”。
本次迭代(V3)在V2基础上的主要增量
引入旅客实体:新增旅客及行李的管理,旅客体重按标准值(75kg)自动计算。
引入核心业务算法:新增基于物理力矩的“航空器载重平衡计算”功能。
增强鲁棒性要求:在数据录入过程中,要对数据进行合法性验证,如果发现有非法输入,立即停止应用程序运行。
【设计要求】
本次迭代新增约4个类,系统总类数达到10个左右。严禁使用继承和多态(无extends、无interface、无instanceof),请严格遵循以下关系与单一职责设计(违反设计要求则扣分):
新增类 职责划分 类间关系设计建议
Passenger 仅负责管理旅客姓名及计算旅客总重量(含标准体重) 与 Luggage 是组合关系。旅客登机必带行李(可为0kg),行李对象必须在 Passenger 构造器内部 new 出来,不对外暴露修改
Luggage 仅负责记录行李重量 作为 Passenger 的组成部分,体现类的细粒度拆分
WeightBalanceCalculator 纯计算工具类。仅负责根据航空力学公式计算总重量、总力矩、重心及百分比。 与 Flight 是依赖关系。该类不应有 Flight 的成员变量,必须将 Flight 对象作为 generateLoadSheet 方法的参数传入
InputValidator (优化) 剥离所有控制台的异常处理逻辑,提供统一的获取整数、浮点数的静态方法 与主流程是依赖关系
注:原有的 Flight 类需增加List 属性,体现关联关系。原有的 LoadDispatcher(排序)在本次生成报告时需被内部调用。另外,本次作业中的排序算法不允许使用朗姆达表达式及Collections.sort()方法,必须使用循环完成排序过程(算法采用冒泡排序)
输入格式:
第1行,航班号(字符串)
第2行,前舱货架行号(整型,≥0)
第3行,前舱货架列号(整型,≥0)
第4行,前舱最大载重量(实型,≥0.0)
第5行,后舱货架行号(整型,≥0)
第6行,后舱货架列号(整型,≥0)
第7行,后舱最大载重量(实型,≥0.0)
第8行,乘客人数n(整型,≥0)
从第9行开始,连续n行,输入每名乘客所携带行李重量(实型数,≥0.0)
货物总件数m(整型,≥0)
装载在前舱的货物件数p(整型,0≤p≤m)
接下来连续输入装载在前舱的p件货物的信息,分别为:
货物编号(整型,≥0)
货物重量(实型,≥0.0)
在输入装载在后舱的m-p件货物的信息,分别为:
货物编号(整型,≥0)
货物重量(实型,≥0.0)
输出格式:
所有输入数据均正常,输出格式如下(加粗斜体字部分为输出的实际数据):

航班 航班号 载重平衡舱单

【基础数据】
空机重量: 重量值 kg | 力臂: 力臂值 m
【旅客数据】
旅客人数: 人数 | 总重(含行李): 总重量 kg
【货物数据】
[1] 装载: 装载重量kg / 最大载重量kg (力臂: 力臂值m)
->[货物编号, 货物重量kg]
注:装载了多少件货物则显示多少行,后舱相同
[2] 装载: 装载重量kg / 最大载重量kg (力臂: 力臂值m)
->[货物编号, 货物重量kg]
->[货物编号, 货物重量kg]
注:[1]代表前舱,[2]代表后舱
【汇总计算】
起飞总重量: 重量值 kg
总力矩:总力矩值 kg·m
实际重心(CG): 重心值 m
重心百分比(%MAC): 百分比值%

配平评估: 危险 (RED - 超出极限重心范围)
配平评估: 安全 (GREEN)
注:以上评估结果二选一

注:输出的实型数均保留一位小数。
数据输入有误的处理
所有检测到输入的数值如果为负数,则输出数值不能为负数!,程序停止运行
如果检测到输入的数值超过应有范围,则提示输入必须在 最小值 到 最大值 之间!,程序停止运行
前舱装载量超过最大装载量,提示:!!! 警告:[1]剩余容量不足(当前载重载重量值/最大载重量kg),请重新分配或减轻重量!
后舱装载量超过最大装载量,提示:!!! 警告:[2]剩余容量不足(当前载重载重量值/最大载重量kg),请重新分配或减轻重量!
实现方法(代码如下)

系统架构与设计理念
1.1 系统架构层次
用户界面层 → 业务逻辑层 → 数据处理层 → 数据模型层
用户界面层:Main类,处理用户输入输出
业务逻辑层:WeightBalanceCalculator、LoadManifest、CargoSorter
数据处理层:InputValidator
数据模型层:Flight、Passenger、CargoCompartment、Cargo、Luggage、Position
1.2 核心设计思想
重心平衡计算:航空工程学应用
安全配载验证:多重安全约束检查
模块化设计:职责分离原则
实时预警机制:超载和重心偏移预警
核心类详细解析
2.1 数据模型类
2.1.1 Flight(航班类)
核心职责:
航班基础信息管理
旅客和货物容器管理
初始化货舱配置
关键属性:
passengers:旅客列表
Weight:空机重量(40000.0kg)
compartments:货舱数组(2个货舱)
LevelofCentral:空机重心力臂(16.25m)
levelofPassenger:旅客力臂(18.0m)
核心方法:
initCargoCompartment():初始化前后货舱
addPassenger():添加旅客
getter方法:获取旅客和货舱信息
2.1.2 Passenger(旅客类)
核心职责:
旅客基本信息管理
行李管理
总重量计算
关键属性:
name:旅客姓名
luggages:行李列表
Weight:旅客标准重量(75.0kg)
核心方法:
TakeLuggage():添加行李
getTotalWeight():计算旅客总重量(体重+行李)
2.1.3 CargoCompartment(货舱类)
核心职责:
货舱配置管理
货物存储管理
实时重量监控
关键属性:
name:货舱名称(前舱/后舱)
id:货舱ID
maxLoadWeight:最大载重量
level:力臂距离
cargos:货物列表
positions:位置数组(扩展功能)
核心方法:
addCargo():添加货物
NewWeight():计算当前货物总重量
getter方法:获取货舱信息
2.1.4 Cargo(货物类)
核心职责:
货物信息管理
按编号排序支持
关键属性:
name:货物名称
weight:货物重量
code:货物编号(排序依据)
核心方法:
getter/setter方法
2.1.5 Luggage(行李类)
核心职责:
行李重量管理
关键属性:
weight:行李重量
核心方法:
getter/setter方法
2.1.6 Position(位置类)
核心职责:
二维位置坐标管理
预留货舱网格化布局功能
关键属性:
x:横坐标
y:纵坐标
核心方法:
getter/setter方法
2.2 业务逻辑类
2.2.1 WeightBalanceCalculator(重量平衡计算器)
核心职责:
飞机配平计算
重心位置计算
安全评估
载重平衡舱单生成
关键常量:
EMPTY_WEIGHT:空机重量 40000.0kg
EMPTY_ARM:空机力臂 16.25m
PASSENGER_ARM:旅客力臂 18.0m
FRONT_CARGO_ARM:前货舱力臂 12.0m
REAR_CARGO_ARM:后货舱力臂 22.0m
MAC_LENGTH:平均空气动力弦长度 5.0m
MAC_LEADING_EDGE:前缘位置 15.0m
SAFE_CG_MIN:安全重心下限 25.0%
SAFE_CG_MAX:安全重心上限 38.0%
核心计算方法:
重量计算
CalculateTotalWeightOfPassenger():旅客总重量
CalculateTotalWeightOfCompartment():货物总重量
CalculateTotalWeightall():起飞总重量
力矩计算
CalculateTotalPowerRetangleOfPassenger():旅客总力矩
CalculatePowerRetangleOfCompartment():货物总力矩
CalculatePowerRetangleall():总力矩
重心计算
CalculateActuallCentralPoint():实际重心位置
重心百分比 = (实际重心 - MAC_LEADING_EDGE) / MAC_LENGTH × 100%
安全评估
safe():检查重心是否在安全范围内
报表生成
generateLoadSheet():生成完整的载重平衡舱单
2.2.2 CargoSorter(货物排序器)
核心职责:
货物按编号排序
使用选择排序算法
支持货舱内货物管理
核心方法:
sort():对货物列表按编号升序排列
时间复杂度:O(n²)
稳定排序
2.2.3 InputValidator(输入验证器)
核心职责:
输入数据验证
非负检查
范围验证
核心方法:
AllDate():检查数值是否非负
应用场景:所有重量、数量、尺寸输入
2.2.4 LoadManifest(装载清单)
核心职责:
结果输出
警告信息显示
用户反馈
核心方法:
printResult():输出结果信息
printWarning():输出警告信息
系统工作流程
3.1 数据输入阶段
输入顺序:

  1. 航班号2. 前舱行数3. 前舱列数4. 前舱最大载重5. 后舱行数6. 后舱列数7. 后舱最大载重8. 旅客人数9. 各旅客行李重量(按人数)10. 货物总数11. 前舱货物数量12. 前舱货物信息(编号 + 重量,重复)13. 后舱货物信息(编号 + 重量,重复)
    输入验证:
    所有数值必须≥0
    前舱货物数≤总货物数
    实时重量检查
    3.2 数据处理阶段
    处理步骤:
    创建航班对象:初始化空机和货舱配置
    添加旅客:创建旅客对象并添加行李
    前舱货物装载
    验证容量限制
    添加货物到前舱
    按编号排序货物
    后舱货物装载
    验证容量限制
    添加货物到后舱
    按编号排序货物
    重量平衡计算:计算实际重心位置
    安全评估:检查重心安全范围
    生成报表:输出完整载重平衡舱单
    3.3 容量检查机制
    实时检查逻辑:
    if (当前重量 + 新货物重量 > 货舱最大载重) { 输出容量不足警告
    终止程序
    }
    航空工程学原理应用
    4.1 重心计算模型
    计算公式:
    总力矩 = Σ(重量ᵢ × 力臂ᵢ)
    实际重心 = 总力矩 / 总重量
    重心百分比 = (实际重心 - MAC前缘) / MAC长度 × 100%
    力臂设定:
    空机:16.25m
    旅客:18.0m
    前货舱:12.0m
    后货舱:22.0m
    4.2 安全边界条件
    安全重心范围:25.0% ≤ 重心百分比 ≤ 38.0%
    MAC长度:5.0m
    MAC前缘位置:15.0m
    4.3 物理意义
    力矩:重量对参考点的旋转效应
    重心:重量的平均位置
    重心百分比:在MAC上的相对位置
    安全范围:保证飞机稳定性和操控性
    系统输出详解
    5.1 载重平衡舱单格式
    ====================================== 航班 [航班号] 载重平衡舱单
    ======================================
    【基础数据】
    空机重量: 40000.0 kg | 力臂: 16.25 m
    【旅客数据】
    旅客人数: [人数] | 总重(含行李): [重量] kg
    【货物数据】
    [前舱] 装载: [当前重量]kg / [最大载重]kg (力臂: 12.0m)
    ->[货物编号, 重量kg]
    [后舱] 装载: [当前重量]kg / [最大载重]kg (力臂: 22.0m)
    ->[货物编号, 重量kg]
    【汇总计算】
    起飞总重量: [总重] kg
    总力矩: [力矩] kg·m
    实际重心(CG): [重心] m重心百分比(%MAC): [百分比]%
    ======================================配平评估: 安全 (GREEN)/危险 (RED - 超出极限重心范围)
    ======================================
    5.2 预警信息格式
    容量不足警告:
    !!!警告:[货舱号]剩余容量不足(当前载重[当前重量]kg/[最大载重]kg),请重新分配或减轻重量!
    输入错误警告:
    数值不能为负数!
    输入必须在 最小值 到 最大值 之间!
    处理数据时发生错误: [错误信息]

类图如下
image

Bug分析如下
image

  1. 分支覆盖率仅 16.7% → 关键逻辑未测试
    代码中大量 if分支未被覆盖:
    if(TotalWeightall==0)→ 防止除零,是否测试了总重量为0的情况?
    return percentage>=SAFE_CG_MIN && percentage<=SAFE_CG_MAX→ 重心安全判断,是否测试了“安全”“偏前”“偏后”三种情况?
    if(parts.length<4)(在 InputValidator 之前)→ 输入校验缺失,测试是否覆盖了异常输入?
    这些分支在报告中未被覆盖,导致覆盖率极低。
  2. 语句覆盖率约 40%(42/104)→ 大量计算逻辑未执行
    总行数 104,语句数 42,说明:
    CalculateTotalWeightOfPassenger()→ 是否测试了空列表、单元素、多元素?
    CalculatePowerRetangleOfCompartment()→ 是否测试了空舱、满载舱?
    generateLoadSheet()→ 是否测试了真实数据输出?(虽然输出是打印,但逻辑应被调用)
    safe()→ 是否测试了边界值(25.0 和 38.0)?
    这些计算方法在测试中未被充分调用,导致语句覆盖低。
  3. 命名不规范 + 代码可读性问题
    CalculateTotalPowerRetangleOfPassenger→ 应为 CalculateTotalMomentOfPassenger(力矩不是“功率矩形”)
    NewWeight()→ 应命名为 getCurrentWeight()或 getTotalWeight()
    getLevel()→ 应为 getArm()(力臂)
    ActuallCentralPoint→ 拼写错误,应为 ActualCenterOfGravity
    命名混乱影响可维护性,也影响测试定位。
  4. 缺少异常处理 & 边界测试
    未处理 passengers == null、compartments == null
    未测试 passengerCount != passengers.size()的情况
    未测试 cargo.getCode()为 null 的情况

踩坑心得
在第一次作业中,我的主要目标是实现基本的配载计算功能。在源码提交和测试过程中,暴露出的最大问题是对Java输入流机制的不熟悉。
编写错误:我在Main方法中混用了sc.nextDouble()和sc.nextLine()。由于nextDouble()读取完数字后不会处理末尾的换行符,导致紧随其后的nextLine()直接读取了空行,程序逻辑直接错乱。当时为了修复这个Bug,我只是在中间随意加了一个空的nextLine()去“抵消”,这种写法非常不规范。
测试数据不足:提交时的测试报告显示分支覆盖率极低(仅16.7%)。因为我只测试了“输入全是正确数字”的正常情况,完全没有考虑到用户可能会输入负数、字母或者空数据,导致程序的健壮性极差。
心得:这次作业让我明白,基础的输入输出处理不能想当然,必须彻底搞懂输入流缓冲区的原理,否则后续开发会一直受困于这种低级错误。

第二次作业增加了货舱和货物的概念,业务逻辑变得复杂,代码量的增加让复制粘贴开始显现。
代码复用率低:在V1.0中,我把冒泡排序的算法直接写死在了主流程里。到了V2.0,当需要按重量对货物进行排序时,我不得不把同一段排序代码又复制了一遍。这不仅让代码变得冗长,而且一旦排序规则需要修改,我就得在多处同时修改,极易遗漏。
类设计结构不合理:当时的类设计非常扁平,Main类承担了输入校验、排序、计算等所有职责,严重违反了单一职责原则。
心得:这次迭代让我深刻体会到,如果前期不做好代码复用和类结构设计,随着功能增加,代码维护成本会呈指数级上升。提取公共方法(如排序工具类)是必须迈出的第一步。

第三次作业引入了旅客和行李,并严格要求遵循面向对象设计原则,这是代码质量提升最大的一次。
工程化与常量管理:在之前的代码中,我到处写死“40000.0”(空机重量)、“5.0”(MAC长度)等魔法数字。在V3.0中,我将这些全部提取为static final常量,集中管理。这不仅提高了代码可读性,也避免了因数字写错导致的计算偏差。
边界条件与防御性编程:针对之前测试覆盖率低的问题,我专门引入了InputValidator类,对所有输入进行统一校验(如拦截负数、非法字符)。同时,在计算重心时,我补充了多组边界测试数据(如重心偏前、偏后、正常范围),确保计算逻辑在各种极端情况下都能给出正确反馈。
心得:通过引入校验类和常量管理,程序的稳定性大幅提升。这次作业让我真正理解了什么是“防御性编程”,即永远不要信任外部输入,必须通过严格的校验和清晰的类结构来保证系统的健壮性。

总结与反思
这三次作业下来,我最大的收获是终于搞懂了怎么用Java真正写一个项目,而不是只写几个孤立的方法。
首先,我学会了怎么处理输入。以前我只会用Scanner乱写,结果老是出现回车符吞掉数据的问题。后来我明白了必须统一处理输入流,要么全用nextLine,要么在中间加空行吸收,不能混用。
其次,我搞懂了面向对象的核心,就是“一个类只干一件事”。一开始我把所有代码都堆在Main里,后来我把计算重心的逻辑拆出去放到WeightBalanceCalculator里,把输入校验拆出去放到InputValidator里。这样改代码的时候,去对应的类改就行,不会牵一发而动全身。
最后,我学会了用常量。以前我把40000.0这种数字到处写死,后来我把它们定义成static final,改参数的时候终于不用满篇找数字替换了。
哪些地方需要进一步学习及研究
我的代码还有很多烂地方,主要集中在测试和规范上。
第一,我的测试太烂了。三次作业的分支覆盖率都只有16.7%,说明我只测了正常情况,没测异常。比如我从来没测过输入负数怎么办,输入字母怎么办,或者除法除零怎么办。以后我得先写一堆异常测试用
例,再写代码。

第二,我的命名太随意了。比如我把“力矩”写成PowerRetangle,把“实际重心”拼错,方法名也经常首字母大写或者用拼音。以后我得严格按照驼峰命名法来,不懂的术语去查字典,不能自己造词。

第三,我对异常处理的理解还停留在if-else判断上,没用好try-catch。以后我得研究怎么抛出具体的异常类型,而不是只打印一个错误信息就完事。

对教师、课程、作业、实验、课上及课下组织方式等方面的改进建议及意见
希望能给更多的测试用例。现在给的样例太少,而且只有正常数据,没有异常数据。导致我们交上去之后才发现覆盖率极低。如果能多给几个边界测试数据,比如空输入、负数输入、超长字符串,我们就能少踩很多坑。

posted @ 2026-05-18 22:57  violetcrystal  阅读(3)  评论(0)    收藏  举报