当前位置: 首页 > news >正文

NCHU航空器配载与货运管理系统作业总结

这三次作业是南昌航空大学Java课程的一个系列实践项目,围绕航空器配载与货运管理这个真实业务场景展开,从第一次的基础货运配载,到第二次的多货舱管理,再到第三次的配平计算,难度是逐级递增的
知识点覆盖:类的单一职责原则(SRP)、对象组合与聚合关系、集合框架的使用、排序算法的手写实现、输入校验与异常处理、以及航空载重平衡中的物理公式计算,以及力矩、重心、MAC百分比
第一次属于基础题,只要理解类职责、会排序输出即可,第二次开始出现货舱和位置的组合关系、货物的聚合关系,需要理清不同类之间的关联,第三次的难度跃升最大——不仅要处理更多类的协作,还要理解物理公式,并对异常输入做严格校验
三次作业整体设计得不错,层层递进,能让人逐步建立面向对象的思维,不过我在做的时候也踩了一些坑,
(一)
第一次作业集包含四个类:Flight、Cargo、LoadDispatcher、InputValidator,
Flight类负责存储航班基本信息(航班号、最大起飞重量、最大业载重量)以及装载的货物列表,Cargo类很简单,就是货物名称和重量,LoadDispatcher负责排序和装载的核心逻辑,InputValidator负责输入校验
排序部分手写了冒泡排序,如以下代码:
public static void sortByWeightDesc(List cargos) {
for (int i = 0; i < cargos.size() - 1; i++) {
for (int j = 0; j < cargos.size() - 1 - i; j++) {
if (cargos.get(j).getWeight() < cargos.get(j + 1).getWeight()) {
Cargo temp = cargos.get(j);
cargos.set(j, cargos.get(j + 1));
cargos.set(j + 1, temp);
}
}
}
}

装载过程在主循环中实时计算总重量并判断是否超载:
double currentTotal = 0;
for (Cargo c : cargos) {
if (currentTotal + c.getWeight() <= flight.getMaxWeight()) {
currentTotal += c.getWeight();
flight.addCargo(c);
System.out.printf("货物[%s 重量:%.1fkg]\n", c.getName(), c.getWeight());
} else {
System.out.printf("货物[%s 重量:%.1fkg] 装载失败,超载\n", c.getName(), c.getWeight());
}
}

使用SourceMonitor对第一次作业进行静态分析的结果:
总行数:约95行
语句数:约42条
复杂度:主要方法的圈复杂度在2-3之间,结构清晰
注释率:过低,后续作业应增加关键方法的注释

第一次作业相对简单,核心是理解SRP原则,我的做法是把输入校验交给InputValidator,排序装载交给LoadDispatcher,航班信息和货物聚合交给Flight,职责划分还算清晰,有一点体会,刚开始容易把很多逻辑都塞进Main类,后来才意识到这样会破坏单一职责

(二)
第二次作业在第一次基础上新增了货舱管理相关的类:Position、CargoCompartment,并且Flight类中增加了货舱列表,同时LoadDispatcher的职责也扩展了—,不仅要排序,还要根据货物指定的货舱ID尝试装载
这是我做的类图设计:
Position

  • row: int
  • column: int
  • getPosName(): String

CargoCompartment

  • id: String
  • maxWeight: double
  • positions: List (组合)
  • cargos: List (聚合)
  • addCargo(Cargo): boolean
  • getCurrentWeight(): double

Flight

  • flightNo: String
  • maxTakeoffWeight: double
  • maxPayloadWeight: double
  • compartments: List
  • getTotalWeight(): double

LoadDispatcher

  • sortCargos(List): void
  • findCargoByName(List, String): Cargo

Position与CargoCompartment是组合关系:就是指货舱创建时内部生成Position列表,货舱销毁时位置也随之消失,这部分代码设计如下:
public CargoCompartment(String id, double maxWeight, int rows, int cols) {
this.id = id;
this.maxWeight = maxWeight;
this.positions = new ArrayList<>();
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= cols; j++) {
positions.add(new Position(i, j));
}
}
this.cargos = new ArrayList<>();
}

Cargo与CargoCompartment是聚合关系:货物可以独立存在,可以被装载到不同货舱,货舱销毁后货物对象仍然存在,这一点在第二次作业中体现得不明显,但到了第三次作业,货物需要根据前舱/后舱分别统计,聚合关系的意义就体现出来了

第二次作业代码行数膨胀到了约220行,主要方法是addCargo和sortCargos,复杂度略有上升,因为货舱查找和容量判断的逻辑增加了分支,使得代码的实现更加困难
这次作业最大的收获是理解了组合和聚合的区别,组合是“整体拥有部分”,部分不能脱离整体单独存在,聚合是“整体包含部分”,部分可以独立于整体,用货舱和位置的例子来理解,非常直观,另外,排序时同等重量的货物按输入顺序排列,这一点通过冒泡排序的稳定性就能保证——只要在重量相等时不交换位置,就能维持原始顺序

(三)
第三次作业新增了Passenger、Luggage、WeightBalanceCalculator三个类,并对InputValidator进行了增强,Flight类增加了List属性
以下是设计的类图:
Passenger

  • name: String (假设为"旅客")
  • luggage: Luggage (组合)
  • getTotalWeight(): double

Luggage

  • weight: double

WeightBalanceCalculator

  • generateLoadSheet(Flight): void (静态方法,纯计算)

InputValidator (增强)

  • getPositiveInt(Scanner, String): int
  • getNonNegativeDouble(Scanner, String): double
  • getIntInRange(Scanner, String, int, int): int

WeightBalanceCalculator类的calculateCG方法接收Flight对象作为参数,从而执行所有计算,代码如下:
public static void generateLoadSheet(Flight flight) {
final double EMPTY_WEIGHT = 40000.0;
final double EMPTY_ARM = 16.25;
final double PASSENGER_ARM = 18.0;
final double FRONT_CARGO_ARM = 12.0;
final double REAR_CARGO_ARM = 22.0;
final double MAC_LENGTH = 5.0;
final double MAC_LE = 15.0;

double passengerTotalWeight = 0;
for (Passenger p : flight.getPassengers()) {passengerTotalWeight += p.getTotalWeight();
}
double passengerMoment = passengerTotalWeight * PASSENGER_ARM;double frontCargoWeight = 0, rearCargoWeight = 0;
for (CargoCompartment comp : flight.getCompartments()) {if ("前舱".equals(comp.getId())) {frontCargoWeight = comp.getCurrentWeight();} else if ("后舱".equals(comp.getId())) {rearCargoWeight = comp.getCurrentWeight();}
}
double cargoMoment = frontCargoWeight * FRONT_CARGO_ARM + rearCargoWeight * REAR_CARGO_ARM;double totalWeight = EMPTY_WEIGHT + passengerTotalWeight + frontCargoWeight + rearCargoWeight;
double totalMoment = (EMPTY_WEIGHT * EMPTY_ARM) + passengerMoment + cargoMoment;double actualCG = totalMoment / totalWeight;
double cgPercent = ((actualCG - MAC_LE) / MAC_LENGTH) * 100;boolean isSafe = (cgPercent >= 25.0 && cgPercent <= 38.0);

}

InputValidator类在第三次作业中被扩展,提供了多个静态方法用于校验不同类型的输入:
public static int getPositiveInt(Scanner scanner, String fieldName) {
int value = scanner.nextInt();
if (value < 0) {
System.out.println("数值不能为负数!");
System.exit(0);
}
return value;
}

public static double getNonNegativeDouble(Scanner scanner, String fieldName) {
double value = scanner.nextDouble();
if (value < 0) {
System.out.println("数值不能为负数!");
System.exit(0);
}
return value;
}

下图是我根据第三次作业的最终代码生成的类图:
┌─────────────────┐ ┌─────────────────┐
│ Flight │────▶│CargoCompartment │
├─────────────────┤ ├─────────────────┤
│-flightNo │ │-id │
│-maxTakeoffWeight│ │-maxWeight │
│-maxPayloadWeight│ │-positions │
│-compartments │ │-cargos │
│-passengers │ └────────┬────────┘
└────────┬────────┘ │
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Passenger │ │ Position │
├─────────────────┤ ├─────────────────┤
│-luggage(Luggage)│ │-row │
│+getTotalWeight()│ │-column │
└────────┬────────┘ └─────────────────┘


┌─────────────────┐ ┌─────────────────┐
│ Luggage │ │ Cargo │
├─────────────────┤ ├─────────────────┤
│-weight │ │-name │
└─────────────────┘ │-weight │
└─────────────────┘

┌─────────────────┐ ┌─────────────────┐
│WeightBalance │ │ InputValidator │
│Calculator │ ├─────────────────┤
├─────────────────┤ │+getPositiveInt()│
│+generateLoad │ │+getNonNegative │
│ Sheet(Flight) │ │ Double() │
└─────────────────┘ └─────────────────┘

第三次作业的总行数接近400行,由于新增了计算类和校验类,代码行数分布相对均匀,WeightBalanceCalculator的generateLoadSheet方法承担了全部计算逻辑,长度约60行,但逻辑上是线性的,圈复杂度不高
这次次作业是三次中收获最大的,物理公式本身不难,难的是如何把这些公式合理地组织到类中,题目要求WeightBalanceCalculator不能持有Flight的成员变量,必须通过参数传递,这个约束迫使我去思考类的依赖关系,
旅客和行李的组合关系也很有意思:行李对象在Passenger构造器内部创建,不对外暴露修改,这样就保证了行李不会脱离旅客单独存在,这个设计在真实业务中很合理——行李总是属于某个旅客的

踩过的坑:
第一次作业的提示中就专门提到了这个问题:nextInt()后敲的回车会被nextLine()读走
我第一次写的时候没注意这个细节,导致输入货物名称的时候总是读不到正确的值,后来按照提示,在nextInt()后面加了一个nextLine()来“吃掉”回车符,问题解决

在判断货舱是否超载时,直接使用currentWeight + cargoWeight <= maxWeight理论上没问题,但浮点数运算存在微小误差,
有一次遇到的情况是:货舱最大载重5000.0,已装4999.9,新货物重量0.1,理论上刚好装下,但由于浮点数精度问题,相加结果可能是5000.0000000001,大于5000,导致误判为超载
解决方法是引入一个很小的容差值,比如1e-6

第二次作业要求“同等重量的货物按输入的先后顺序排列”,冒泡排序在元素相等时不交换位置,天然是稳定的,但我一开始写成了if (list.get(j).getWeight() <= list.get(j+1).getWeight()),这样相等时也会交换,破坏了稳定性改回<就对了

第三次作业的输出中,“整体配载状态”可能有四种情况:正常、超过最大起飞重量、超过最大业载重量、同时超过两个,我一开始只判断了是否超过最大起飞重量,漏掉了最大业载重量的单独判断

还有第三次作业中,每位旅客的总重量 = 75kg(标准体重)+ 行李重量,我在Passenger类中实现了getTotalWeight()方法,一开始犯的错误是把75kg的常量写在了主流程里,违反了类的封装原则,后来改到Passenger内部,更符合面向对象的思想

总结:
做完这三次作业,我主要学会了三件事
第一,类是干嘛的,以前写代码喜欢把一堆东西塞在一起,一个方法里既管输入又管计算还管输出,这次被SRP原则卡了几次后明白了——每个类就干一件具体的事,比如货舱只负责装货和算自己的重量,计算只负责算重心,主类只管调用。代码出了问题,直接去对应的类里找就行
第二,组合和聚合的区别,简单说就是:货舱没了,里面的位置格子也就没了,这叫组合;货舱没了,货物本身还在,这叫聚合。做第二次作业的时候,我把货舱和货物写成了聚合,因为货物可以卸下来放到别的航班上,设计上是对的
第三,排序必须手写,前两次作业不让用Collections.sort(),逼着自己写冒泡排序。一开始觉得麻烦,后来发现手写才能真的理解排序的稳定性是什么——相同重量的货,谁先输入谁排在前面,冒泡只要不交换相等元素就能保证
三次作业做下来,从最简单的装货判断超载,到多货舱管理,再到算重心和MAC百分比,难度一步步上来,但每个阶段的设计要求都跟业务场景对得上,不是凭空造需求,代码写完之后再看,自己确实有进步

http://www.jsqmd.com/news/834715/

相关文章:

  • 2026年家装益胶泥经销商选型指南:实力合规厂商推荐解析 - 产业观察网
  • 2026年5月镇江黄金回收正规靠谱指南:五家机构多维度测评 - 天天生活分享日志
  • 南昌航空大学软院前三次PTA作业集总结blog
  • 2026年5月行业内郑州腻子粉机器设备全自动公司哪家强厂家推荐榜,全自动腻子粉生产线、干粉砂浆搅拌机、真石漆设备厂家选择指南 - 海棠依旧大
  • 2026年5月正规的烟台发电机出租公司口碑推荐厂家推荐榜:静音发电机、移动发电车、高压发电机厂家选择指南 - 海棠依旧大
  • 深耕本地学情|萧山优质学科辅导机构实力全面解析 - 浙江行业评测
  • 2026年家装益胶泥代理商哪家好:行业选型指南与主流品牌实力解析 - 产业观察网
  • 2026年5月:超声波泥位计十大厂家实测盘点 - 水质仪表品牌排行榜
  • 2026年济南市历城区45天拿证的驾照直营驾校/比较好的驾照金牌驾校 /新规学车的驾照标杆驾校 - 品牌推广大师
  • 2026年5月口碑好的抚顺搬家公司如何选厂家推荐榜:居民搬家、公司搬迁、长途搬家、专项搬运、小型搬家厂家选择指南 - 海棠依旧大
  • 2026年5月热门的羊山新区轻法式装修公司如何选厂家推荐榜,一站式整装与全屋定制厂家选择指南 - 海棠依旧大
  • 2026年家装益胶泥代理商选择深度指南:核心评估维度与靠谱品牌推荐 - 产业观察网
  • 2026年4月包头到三亚有实力的汽车租赁公司联系电话,汽车租赁/租车,汽车租赁门店需要多少钱 - 品牌推荐师
  • 镇江黄金回收机构哪家强?整理出这份TOP5靠谱清单(无套路) - 生活测评君
  • 2026年树脂混凝土泵站生产厂家权威推荐榜单:树脂混凝土一体化泵站/树脂混凝土预制泵站/树脂混凝土沉井泵站源头厂家精选 - 泵站报价15613348888
  • 2026年5月值得信赖的团建公司哪家权威厂家推荐榜:户外拓展、主题团建、水上团建、定制化团建全面指南 - 海棠依旧大
  • 2026年5月国产在线浊度仪前五,工程选型必看 - 水质仪表品牌排行榜
  • 南通黄金回收全攻略:六家实体门店横向评测 - 生活测评君
  • 未激活状态天猫超市卡能否合规变现?行业权威规则解读 - 京顺回收
  • 扬州黄金回收哪家靠谱?奢响佳实力领跑全城 - 天天生活分享日志
  • 2026年5月专业的哈尔滨到无锡物流公司哪家靠谱厂家推荐榜,普货整车/零担专线、轿车托运、长途搬家厂家选择指南 - 海棠依旧大
  • 2026年5月液体涡街流量计国产优质品牌实测与选型 - 液体流量液位品牌推荐
  • 2026年5月远传电磁流量计国产厂家精选推荐 - 液体流量液位品牌推荐
  • 航空器配载与货运管理系统
  • 2026年5月水厂超声波液位计十大品牌:国产崛起,进口稳占高端 - 液体流量液位品牌推荐
  • 2026年南通黄金回收门店全维度评测|靠谱/正规/价高精选 - 天天生活分享日志
  • 2026泰州黄金回收靠谱测评|五家门店五维实测全公开 - 天天生活分享日志
  • 2026年5月南宁西乡塘区专业音响改装店推荐榜:DSP调音、无损升级、主动三分频等方案厂家选择指南 - 海棠依旧大
  • 杭州萧山成人高考办学机构实力测评,报名避坑干货 - 浙江行业评测
  • 机械设备外贸网站建设,参数展示选 WaiMaoYa(外贸鸭) - 外贸营销工具