第三次Blog

一、前言
首先对本学期的PTA进行评价,本学期的PTA后面的几次大作业的主要形式是若干个小题加一个迭代作业,每次大作业都会在前一次的基础上进行增加和迭代,主要是对功能进行扩展,第一次的电梯迭代难度较大,后面的航空货物管理难度较为适中,本学期的PTA对于我们类的设计提出了更高要求,每一个大作业结束后就进行一次Blog总结,我认为是十分系统有效的,帮助我们更全面细致的进行学习,其次是实验,从第二到第五的实验都是对动物放进冰箱的迭代,当然后面几次实验扩展了更多功能,总体的难度不大,本学期采取线上的学堂在线和线下课程结合,线上课程主要是让我们了解基本知识包括语法等,这与上学期C语言的学习不同,我认为是更为合理的,对于我们的自主学习能力提出了更大要求。总体的工作量比较适中。

二、面向对象技术总结
(一)封装
在面向对象编程实践中,深刻体会到封装是构建安全、可维护代码的核心机制。通过将类的内部状态(如成员变量)设置为private并辅以规范的访问方法,不仅实现了数据隐藏,更建立了可控的访问边界。比如在模拟电商系统的 “商品类” 开发中,商品价格变量被封装后,可在 setPrice 方法里加入价格合理性校验(如不能为负数、需符合定价规则 ),从源头保障数据质量 。如何精准划分封装边界仍是挑战 —— 大型项目里,模块内部逻辑与对外交互的封装,常因需求频繁变更,出现职责模糊、耦合度意外升高的情况,后续需通过更多实战项目,积累合理封装的经验 。
(二)继承
继承体系在构建类层次结构时展现出强大优势,通过实验项目中的“圆形类,矩形类”设计,验证了代码复用的高效性。从抽象Area基类派生出equal,Circle等子类时,既继承了通用属性(如载客量、速度),又通过方法重写实现了差异化的move()行为。但深入使用后发现了继承的局限性:首先,"钻石问题"在多层继承中难以规避,即使通过接口补偿也增加了复杂度;其次,父类方法在子类中的重写可能破坏"里氏替换原则",近期作业中就出现过因重写equals()方法不当导致的集合操作异常,这提示需要更深入理解继承契约。

(三)多态
多态特性让系统具备了动态扩展能力,在开发插件化架构时尤为显著。通过定义Decoder接口规范decode()方法,使得MP3Decoder、FLACDecoder等实现类可以运行时替换。但面对复杂类型系统时仍存在困惑:当泛型边界<? extends Base>与多态结合时,编译器对方法调用的限制规则;特别是接口默认方法与类继承方法冲突时的优先级判定,这些都需要通过JVM规范学习来弥补认知盲区。近期尝试用策略模式重构支付模块时,就因对运行时绑定机制理解不深导致类型转换异常。

(四)抽象类
作为模板方法的载体,抽象类在框架开发中展现出独特价值。例如在实现跨平台渲染引擎时,抽象类GraphicsContext既规定了render()等必须实现的方法,又提供了通用的资源管理模板。但在实际应用中常陷入设计困境:当抽象类包含超过3个抽象方法时,是否应该拆分为接口?在最近图像处理库开发中,就因抽象类同时承担状态管理和行为定义双重职责,导致子类被迫实现无关方法。这提示需要结合"接口隔离原则"重新审视抽象类的设计边界。

(五)接口
Java8后的接口革新使其成为行为抽象的首选工具。通过开发可插拔的日志系统,实践了接口的多种应用:函数式接口@FunctionalInterface支持Lambda表达式、默认方法实现接口演进、静态方法封装工具逻辑等。特别在微服务架构中,FeignClient通过接口定义HTTP请求,展现了"契约优于实现"的威力。但目前对接口组合技巧掌握不足——当多个接口存在相同默认方法时,如何在实现类中显式解决冲突?如何设计合理的接口继承层次?这些都需要更多实例来进行实践。

(六)集合框架
集合库的深入使用显著提升了数据处理效率。通过项目实战积累了丰富经验:用LinkedHashMap实现LRU缓存、TreeSet维护有序数据集、ConcurrentHashMap解决线程安全问题等。但在复杂场景下仍存在短板:①Collections.unmodifiableList的防御性拷贝实际是浅拷贝,曾因此导致嵌套集合被意外修改;②流式操作与传统集合的混合使用时性能优化(如短路操作findFirst与limit的差异);③自定义集合类实现fail-fast机制的具体规范,这些都需要通过源码阅读来深化理解。

(七)异常
完善的异常处理机制是系统稳定性的保障。在分布式系统开发中,逐步形成了分层处理策略:底层用Checked Exception处理可恢复错误(如数据库重连),业务层用Unchecked Exception处理逻辑错误,顶层用全局异常处理器统一包装响应。但异常设计仍存在改进空间:①过度使用异常导致性能损耗(如用异常控制循环流程);②自定义异常的上下文信息传递不够丰富(缺少错误码、国际化支持等);③Java7的try-with-resources在管理非AutoCloseable资源时的适配方案。

(八)JavaFX
实践让我掌握了响应式界面构建技巧。在GUI开发实践中,深刻体会到JavaFX组件化架构的强大之处。通过系统学习掌握了核心UI组件的特性与应用场景,Label与Text组件灵活搭配,支持动态数据绑定和富文本展示,Button绑定事件处理器完成交互响应,通过CSS美化实现悬浮/点击态效果,利用WebView嵌入HTML内容,实现混合式开发,这些需要通过图形学相关知识的补充来完善。

(九)并发编程
多线程开发是Java能力的重要组成。通过实现高并发订单系统,掌握了线程池参数调优(核心线程数/队列容量/拒绝策略的关联)、CompletableFuture异步编排、ThreadLocal防内存泄漏等关键技术。但面对复杂场景仍显吃力:①JUC原子类与synchronized的选型依据;②ForkJoinPool工作窃取算法在实际任务中的性能表现,这些我都要进行进一步学习。

总体而言,面向对象基础已建立系统认知,但在设计模式的合理运用、类型系统的深入理解、性能优化的工程实践等方面仍需加强。特别是需要将离散的知识点串联起来,例如在Spring框架中如何通过接口+动态代理实现AOP,这种跨领域的知识融合能力将是后续重点提升目标。计划通过参与开源项目,在真实代码环境中深化对Java技术栈的整体把握。

三、踩坑心得
1.面向对象设计原则的实践偏差

在电梯模拟系统的首次实现中,笔者犯了一个典型的新手错误——将所有业务逻辑(包括电梯运行控制、请求调度、状态监控等)都塞入单个Elevator类中。这个"全能类"最终膨胀到500余行代码,方法嵌套层级达到7层,圈复杂度高达23。这直接导致了两个严重后果:首先,在高峰期请求量增大时出现明显的性能瓶颈;其次,当需要新增VIP电梯功能时,修改原有代码的风险极高。类似的问题也出现在航空货运系统中,由于没有将输入输出处理独立为专门的IOHandler类,导致业务逻辑与界面呈现高度耦合,后续增加XML格式支持时不得不重构整个主类。

2.继承体系的误用与多态陷阱

在改进电梯系统时,曾试图通过让Elevator类继承Logger基类来添加日志功能,这直接违反了"组合优于继承"的原则。当需要切换日志实现方式时,不得不修改所有子类。在图形处理作业中,Ball类同时承担了几何计算和序列化双重职责,还通过多层继承(Ball→RoundShape→Shape)引入了不必要的复杂性。更糟糕的是,在重写equals()方法时没有同步修改hashCode(),导致对象在HashSet中出现重复问题。这些经历让笔者深刻认识到:继承应该严格用于表达"is-a"关系,且必须遵守里氏替换原则。

3.输入输出处理的常见陷阱

格式规范方面,曾因电梯系统输出中多余的空格字符导致自动化评测失败;日期处理时没有使用DateTimeFormatter而直接拼接字符串,造成不同地区的时间解析差异。在航空货运系统中,没有对用户输入的货物重量做范围校验(weight > 0),导致后续计算出现负数异常。最严重的一次是在文件操作时,使用FileWriter而没有指定字符编码,在Linux服务器上出现了中文乱码问题。现在会严格遵循以下规范:
使用System.lineSeparator()代替硬编码的"\n"
数值输入必做范围校验
所有IO操作都显式指定UTF-8编码
使用try-with-resources确保资源释放

4.算法与数据结构的经验教训

电梯调度算法最初使用ArrayList存储请求队列,导致在中间位置插入新请求时产生O(n)的时间开销,当请求量达到1000+时出现明显延迟。改用LinkedList结合PriorityQueue后,插入效率提升到O(log n)。在图形排序任务中,自己实现的冒泡排序算法比Collections.sort()慢15倍以上,而且没有考虑Comparator的链式组合,导致多条件排序逻辑混乱。此外,在最近的项目中还发现:
频繁调用List.contains()进行存在性判断(O(n)),应改用HashSet(O(1))
在多线程环境下错误使用HashMap导致并发修改异常
没有合理设置ArrayList的初始容量,导致频繁扩容

5.Java学习中的其他典型误区
(1) 异常处理表面化:早期习惯用catch(Exception e)笼统处理所有异常,掩盖了真实的程序问题。现在会区分检查异常和非检查异常,对SQLException等特定异常做针对性处理。
(2) 字符串拼接滥用:在循环体内使用"+"拼接字符串,没有意识到StringBuilder的重要性,当处理大文本时产生大量临时对象。
(3) 静态方法滥用:将工具方法全部定义为static,导致代码难以测试和扩展,后来改用依赖注入改善可测试性。
这些教训促使笔者建立了严格的代码审查清单:每个类不超过200行、方法圈复杂度控制在10以内、所有输入参数必须校验、优先使用JDK内置算法库。实践证明,只有通过这种"踩坑-分析-改进"的循环,才能真正掌握Java编程的精髓。

四、改进建议与总结
1.学习方法改进
理论与实践结合
在理解面向对象基础概念(如封装、继承、多态)时,建议结合具体代码案例进行实践,例如通过小型项目(如简易银行系统、学生管理系统)巩固知识点。
对于抽象概念(如接口、抽象类),可借助UML类图辅助理解,并在实际编码中体会其设计优势。
迭代式学习与复盘
每次PTA作业完成后,建议整理易错点并分析原因(如设计模式应用不当、边界条件未考虑),形成个人“避坑指南”。
通过Blog总结提炼核心收获,例如对比继承与组合的适用场景,或总结异常处理的最佳实践。
主动拓展学习
对于薄弱环节(如JavaFX事件驱动、并发编程),可通过开源项目(如GitHub上的JavaFX案例)或技术文档(如Oracle官方教程)补充学习。
建立代码审查习惯,与同学互相评审代码,学习不同的设计思路。

2.课程优化建议
教学内容调整
基础与进阶分层:将课程内容划分为“核心语法”(学生自学+测验)和“高阶应用”(课堂精讲+实战),例如多线程和集合框架可作为重点授课内容。
案例多样化:减少单一实验主题的重复迭代(如“动物与冰箱”),增加不同场景的实践(如电商订单系统、交通调度模拟),提升学习兴趣。
作业与实验设计
梯度化任务:PTA作业可设置“基础版”和“挑战版”,前者确保所有同学掌握核心要求,后者供学有余力的同学深入探索。
团队协作任务:引入1~2次小组项目(如开发简易GUI应用),培养代码协作和版本管理(Git)能力。
课堂互动增强
即时编程挑战:在讲解设计模式时,可设置10分钟的限时设计题(如用策略模式实现不同排序算法),现场讨论最优方案。
业界案例分享:结合教师经验,分析知名框架(如Spring)中的面向对象设计,帮助学生理解知识在实际工程中的应用。

3.综合性总结
学习成果
系统掌握了面向对象的核心思想,能够合理使用封装、继承、多态构建模块化代码。
通过PTA迭代作业和实验,提升了问题分解能力和代码重构意识,例如在航空货运系统中学会分离IO处理与业务逻辑。
待改进方向
技术深度:对JavaFX事件驱动模型和并发编程的理解仍需加强,计划通过模拟项目(如多线程爬虫)巩固相关知识。
工程规范:需进一步熟悉团队开发流程(如单元测试、文档编写),为后续大型项目打好基础。
长期规划
在实践中提升面向对象设计与系统架构能力。

总结:本学期的课程体系有效培养了面向对象编程思维,后续可通过更灵活的案例设计、阶梯式任务和团队协作进一步优化学习体验。个人也将以“理论→实践→复盘”的循环持续精进技术能力。

posted @ 2025-06-22 17:46  24201513-丁琦  阅读(25)  评论(0)    收藏  举报