跳到正文
GitHub Blog · AI & ML· Julien Dubois·· 3 天前精选AI 评分66

3 位 Java Champion 如何使用 GitHub Copilot 提高开发效率

How 3 Java Champions are using GitHub Copilot for increased productivity

AI 导读

3 位 Java Champion 分享了使用 GitHub Copilot 开发功能、迁移内容和排查缺陷的实践,强调提供上下文、验证结果并由开发者承担交付责任。

推荐理由

将需求澄清、任务专属验收关卡和确定性检查串成反馈闭环,为把智能体的快速执行转化为可维护的软件提供了可迁移方法。

正文 · AI 翻译

AI 编程工具可以快速生成代码,但仅靠速度并不能解决软件工程中最棘手的问题。开发者仍需提供上下文、验证结果、保障可维护性,并对交付的成果负责。

为了了解经验丰富的开发者如何取得这种平衡,我们采访了三位 Java Champion,他们都拥有超过十年的 Java 使用经验。他们分享了在生产环境和开源项目中使用 GitHub Copilot 的具体案例,以及将 AI 生成的输出转化为可靠软件的实践方法。

以下是他们与我们分享的建议。

认识这几位 Java Champion

  • Vlad Mihalcea,Hypersistence 创始人、《High-Performance Java Persistence》一书作者
  • Patrick Baumgartner,42talents 的软件工匠,拥有 20+ 年 Java 经验
  • Frank Delporte,Azul 高级技术文档工程师、Foojay.io 维护者,拥有 15+ 年 Java 经验

Vlad Mihalcea

GitHub 个人主页:@vladmihalcea

GitHub Copilot 最近为你提供了哪些帮助?

我一直在使用它来分析、设计和实现 Hypersistence Utils 和 Hypersistence Optimizer 中的各种功能。

例如,我很早就想开发一个提供 Optimizer 事件历史记录的 Web 应用,以便了解性能优化工作如何体现在应用性能上。在 AI 出现之前,我一直推迟这项任务,因为开发它需要花上几周时间。但使用 Copilot 就像多了一位新团队成员,所以我用它创建了一个应用,将随 Hypersistence Optimizer 的下一个版本一同发布。这项任务只用了两天就实现了,而不是几周。

你通常如何使用 GitHub Copilot?是将它作为 IDE 插件使用,还是使用 GitHub Copilot 应用?

我在 IntelliJ IDEA 中使用 GitHub Copilot,因为在审查源代码或调试时都能方便地使用它。

作为代码助手,它非常有用,既能帮助我加快问题排查,也能加速为需要验证的功能构建原型。

我仍然会审查 AI 生成的计划和代码,因为它们的目的是提高我的生产力,而不是完全取代我。虽然 AI 在许多情况下都能给出正确答案,但有时它的回复仍不尽如人意,需要我介入。

能否分享一些技巧和最佳实践?例如,你在使用哪些技能?

我创建了自己的技能,让 Copilot 生成的任何文本看起来都像是我亲手写的。

这项技能从我已发表的 65 篇文章中提取我的写作风格,因此生成的草稿读起来像我的博客文章,而不像语言模型的输出。在为这个项目生成文档时,这非常有用,因为它能让大语言模型从我 12 年的博客写作中学习,并提供遵循相同原则的示例,例如表达力、可测试性和简洁性。

在我的软件工程师职业生涯中,我认识到,我们花在代码维护上的时间远远多于编写代码。因此,考虑到维护和稳定性对现有产品至关重要,我开发了一些技能,帮助 AI 按照最小惊讶原则模仿现有的代码实践。

一个技巧是根据操作类型切换模型。需要深入思考时,我会使用具有 1 million 上下文窗口的 Opus,并将推理级别设为 Extra High 或 Max。但对于生成报告、发布说明或核验文档等较简单的任务,我会使用消耗更少 token 的轻量模型。

Patrick Baumgartner

GitHub 个人资料:@patbaumgartner

你的工作涉及团队辅导。你采用什么方法?

我开展很多工作时,企业的日常业务仍须照常运转。你不能把一切都停下六个月来进行“转型”。我们通常先一起解决眼前的问题,了解团队目前的状况,明确我们想要达到的目标,以及如何判断自己正在进步,然后一步步朝目标迈进。

视具体情况而定,这可能意味着采用 TDD、重构、持续交付和 XP 等软件匠艺实践;使用 Spring Boot、Spring Modulith 进行架构设计和模块化;应用 Spring Security;针对容器优化 Java 和 Spring Boot 应用;或者越来越多地开展智能体工程。

对我来说,重要的是我是在与团队一起工作。我们共同做决定。我不希望团队变得依赖我。理想情况下,过一段时间后,他们就不再需要我了,或许只需要我充当切磋交流的伙伴。

也许这解释了为什么我觉得新一代 AI 工具如此有趣:我喜欢与人合作、学习、实验和解决问题。AI 为我们提供了又一种非常强大的工具,恰好可以用来做这些事。

能分享一个最近 GitHub Copilot 帮到你的好故事吗?

实际上,有三个截然不同的例子改变了我对使用 GitHub Copilot 开展工作的看法。

我们先从第一个说起吧。

其中一个是将 15 份演示文稿中约 900 张教学幻灯片从 Reveal.js 迁移到 Marp。这些幻灯片并不简单。很多都包含代码、动画,甚至还有交互式示例,让我能在教学时现场修改 JavaScript。更重要的是,这些演示文稿已经在学生课堂上经过了实战检验。讲解流程是行之有效的。丢失任何一个小环节,都可能破坏我在课堂上使用的叙事。

手动完成这次迁移可能需要一周甚至更久——而现实地说,我可能干脆就不做了,因为这项工作实在太枯燥。

有了 Copilot,我采取了不同的做法。我们先分析现有材料,明确目标,制定迁移计划,设定约束,提供示例,并明确哪些内容必须保持不变。然后,我们从大的结构性调整入手,逐步深入细节。

真正重要的环节是验证。

我们生成了 Reveal.js 和 Marp 版本的截图,并通过目视和算法进行比较。我们还构建了一个小应用,让我可以并排运行两套幻灯片,手动核验动画。我们甚至比较了生成的 PDF。

这意味着智能体不只是说一句“迁移完成”。我们有证据。

整个迁移过程大约花了我八到十个小时。我仍然负责内容、教学意图以及每一项实质性改动。Copilot 可以自动修正拼写错误,但如果涉及内容、版本、日期或含义的变化,我们就会一起讨论。

对我来说,这段经历强化了一条重要原则:委派的是执行,而不是责任。我对结果负责。

能分享第二个例子吗?

第二个例子来自使用 Tamboui 构建终端 UI 应用的经历。它起初在 WSL 下的 Linux 中运行得非常好,而我完全忘了可能有人会直接在 Windows CMD 或 PowerShell 中运行它。

然后,还真有用户这么做了。

他们发现,在某些表单中,按 Enter 键根本没有反应。这也印证了我坚信的另一条原则:尽早发布软件,因为你能从人们实际使用它的方式中学到东西。

我们使用 Copilot 将这些反馈转化为可复现的 UI 测试。在 Linux 上,Copilot 通过 tmux 操作应用。在与它协作的过程中,我了解了 psmux,并能在 PowerShell 中执行类似的流程。我们复现了问题,在本地做了修复,追踪到真正的问题出在 Tamboui 中,随后我向上游提交了修复,并获合并。

在这项工作中,测试描述本身变得过于庞大,超出了可用上下文的容量。于是,我请 Copilot 帮我重新设计测试的表示方式。它提议用一种紧凑得多的箭头记法,取代包含标识符、名称和重复描述的冗长表格:步骤 → 步骤 → 输入,只在关键之处补充额外信息。

这让我感到意外。我们不只是在用 AI 执行信息,而是在共同研究应该如何表示信息,以便执行。这种表示方式不必最大限度地便于人类阅读,而是要在保留语义的同时,让智能体能够高效处理。

第三个例子呢?

第三个例子又完全不同。

我身边有人需要练习数学,我就想:为什么不做一个小型学习应用呢?

它涵盖一至四年级的加法、减法、乘法、除法和有余数的除法。但我不想再做一个简单的答题应用。我和 Copilot 一起研究了各种学习方法,包括间隔重复、即时反馈、自适应难度、激励、合作学习,以及不采用暗黑模式的游戏化。

有趣的是,在研究过程中,Copilot 质疑了我最初的一个假设。我原本希望这个应用能通用于世界各地的儿童。但研究促使我们转而关注实际的学校课程。我意识到,各地在知识点的引入顺序、运算和数值范围上存在足够大的差异,因此没必要一开始就把它做成“通用”的应用。

因此,我们先聚焦瑞士,并据此调整学习进度安排。由于瑞士是一个多语言国家,这个应用提供德语、法语、意大利语和英语版本。

它还有合作和对战两种双人模式。当有人答错时,应用会解释一种解题方法,并通过间隔重复再次呈现类似题目。

我特意选择了没有后端的架构。我没有理由在服务器上收集儿童的个人数据,因此数据保留在设备上,而应用只需托管在 GitHub Pages 上即可。

最初的一个小实验,如今已在朋友之间使用和分享。它无意中变成了一个小产品。

这段经历让我看到了 Copilot 的另一面:不要只用它来实现你的解决方案。把它当作切磋伙伴,在开始构建之前,拓展并质疑可能的解决方案范围。

你通常如何使用 Copilot?

其实,我已经不再使用传统的 Copilot 自动补全功能了。

我的工作几乎已经完全转向智能体工作流。

当我需要紧密的视觉反馈循环时,我会使用 VS Code——也就是当我想仔细查看文档、代码、演示文稿或中间结果,并在过程中随时调整流程时。

对于规模更大、侧重执行的任务,我经常在终端中使用编程智能体。在那里,我更习惯把一项工作委派出去,让它执行,然后检查完整的结果。我选择哪种界面,主要取决于我需要怎样的反馈循环。

在前往 JavaLand 的途中,我还体验了一次通过 GitHub 使用编程智能体工作流的过程,非常有意思。当时,我已经开始探索一个 Maven 插件的构想,用来优化 Spring Boot 自动配置的加载选择。在大约四个小时的旅程中,我一直用手机指挥智能体:给它分配任务,审查它完成的工作,思考下一步,然后发送下一条指令。

等我抵达时,我已经有了一个能运行的 Maven 插件、一条 CI 流水线、针对示例应用的性能测试,以及能够证明优化是否真正奏效的报告。

那是我第一次以这种方式工作,我很惊讶它居然真的行得通。我并不是在尝试用手机写 Java,而是在审查、决策和指挥,同时由智能体执行。

当 MCP 服务器能够提供有用的能力或上下文时,我也会使用它们。例如,我用过 Context7 来获取文档,也用过与我的 Logseq 知识库的集成,还尝试过 Adobe Premiere Pro 的 MCP 集成。

但我不会仅仅因为能用就去用 MCP。如果有好用的 CLI,我往往更倾向于使用 CLI,因为对我来说,它感觉更直接、更快捷。

在我的认知中,智能体也不是“初级开发者”。我更愿意把它看作一个切磋伙伴。但就像任何刚加入项目的人一样,它首先需要熟悉项目情况。

上下文为王。

你能分享一些技巧和最佳实践吗?

我最想给出的建议是:停止使用一次性提示。

对于任何并非轻而易举就能完成的任务,我都希望在开始执行之前先理解问题。我经常会明确要求智能体先向我提问。这番问答的目的是挖掘那些尚未明确表达的假设和期望。

一个优秀的智能体可以以惊人的速度执行错误的想法。但这并不会降低走弯路的代价。

我在开发 Spring Boot 自动配置优化器时,亲身经历过这一点。最初,我想同时支持 Spring Boot 3.5 和 4.x。由于架构存在差异,我们实现了两套方案。后来我意识到自己不再需要 3.5 的实现路径,而移除它的过程很痛苦。

教训很简单:走弯路的代价很高。加速之前,先把需求弄对。

意图明确之后,我希望有一份计划。审查这份计划时,我尤其关注四点:假设是否明确呈现,是否定义了验证关卡,方案是否契合架构,以及是否避免了不必要的工作?

第二条原则是定义针对具体任务的验证关卡。

“完成”不应该意味着模型说它完成了。

对于重构,验证关卡可能包括通过测试、证明所有预期文件都已处理、更新文档,以及不留下任何 TODO。对于幻灯片迁移,验证关卡则包括截图、视觉差异对比、动画、PDF 输出和内容完整性。

关卡因任务而异,但原则不变:智能体应当能够提供证据,证明工作符合完成标准。

我最近接触到一个名为 unlazy 的技能,它遵循类似的思路:设立明确的关卡,有条不紊地逐一推进,并证明这些关卡已经完成,而不是走捷径。

第三个原则是将经验教训转化为可复用的技能。

我已经开始编写和维护自己的 Agent Skills。当我从一次执行中学到东西时——可能是智能体误解了某项约定、缺少了一项有用的检查,或是我找到了更好的任务处理方法——我就会更新相应的技能。

下次执行同一任务时,这些经验教训就已经融入其中了。

一个例子是我称为 maintainer-audit 的技能,其灵感来自开放智能体技能社区的工作。我在自己的各个代码仓库中使用它。它会检查,并在适当时修复我期望一个持续维护的项目应当具备的各项内容:代码仓库文档、CI 流水线、Dependabot 配置、CodeQL、统一的清理规范以及其他项目标准。

目标不是再生成一份审计报告让我阅读,而是自动让代码仓库重新接近我期望的基准。这让我的项目更加一致,也更易于维护。

我将这些技能视为持续演进的工程知识,而不是静态的提示词。

第四个原则是在概率性模型周围部署确定性的工程工具。

我有自己的一套质量保障框架,它封装了 Checkstyle、PMD 和 Spring Modulith 架构检查等工具,并生成一份智能体可以读取的综合报告。我可以通过钩子运行它,让智能体不断迭代:

修改 → 执行检查 → 读取发现的问题 → 修复 → 再次执行。

这个过程会一直持续,直到不再发现任何问题。

这并不意味着我不再审视软件。我仍然会运行应用程序,与之交互,并判断它的行为和外观是否符合我的预期。有时我会刻意逐个实现功能,因为这样反馈循环要紧密得多。

我学到的是,仅仅因为“AI 能做到”就一次性要求它完成所有事情,通常不是个好主意。庞大而笼统的规格说明会产生庞大而笼统的实现——事后清理这些实现,可能比以更小的增量正确构建还要困难。

更广泛地说,我认为我们开发者需要更多地讨论我们是如何使用这些工具的。分享成功的实验,也分享失败的实验。相互借鉴想法,再根据自己的具体情境加以调整,而不是寻找一种通用的 AI 开发流程。

这也是我喜欢将 AI 视为切磋伙伴这一想法的原因。在周五晚上,当我想尝试一些东西,却找不到人结对协作时,我突然就有了一个人——或者说某种东西——可以用来质疑一个想法、共同审视一种方法,或者充当一只极其复杂的橡皮鸭。

但我仍然会把这些想法带回去与真实的人讨论。人的反馈、对产品的理解以及现实世界的背景,依然不可或缺。

你认为 AI 正在如何改变我们的职业?

我不认为软件工程专业学生的首要志向应该是成为生产代码的机器。他们需要成为出色的问题解决者。他们需要理解用户和利益相关者,发现需求背后的真正问题,质疑假设,理解产品和市场,做出架构权衡,进行批判性思考,以有条理的方式工作,并将有用的解决方案从一种情境迁移到另一种情境中。

这个模型在生成各种可能方案和执行任务方面表现极其出色。但作为人类,我通常更了解实际背景,包括那些从未有人记录下来的事情。

所以,我希望继续主导解决方案的设计,让智能体承担更多执行工作。

从这个意义上说,我认为AI 正在让软件工程回归工程本质。

而且我喜欢这样。

Frank Delporte

GitHub 个人资料:@FDelporte

你是如何进入科技行业的?

自从 11 岁时得到一台 Commodore 64,我就一直对计算机着迷。毕业后,我曾短暂转向视频制作和电视相关工作,但后来又回到了编程,因为那些视频需要放到 DVD 和最早的一批网站上……没错,我就是这么老了 ;-)。

GitHub Copilot 最近为你提供了哪些帮助?

它是评估拉取请求和调查缺陷报告的理想搭档。

有一个很值得一提的故事,关于 Pi4J 库,它让你能够构建 Java 应用程序,与 Raspberry Pi 上的电子元件交互。在 February 2026,我们发布了 V4,其中包含一个使用 Foreign Function & Memory API 的新插件。发布前,我们进行了充分测试,但发布后不久,仍有人报告说,使用 5 个输入按钮时无法按预期工作。按下已配置的前四个按钮中的任意一个,都会按预期触发代码执行,而第五个按钮则没有任何反应。

这是你最不想收到的那类报告。表面上看不出任何故障。没有异常,日志中没有警告,第五个按钮就是毫无动静。而且情况更糟的是:使用旧版 gpiod 插件时,完全相同的硬件和完全相同的应用程序都能正常工作。因此,问题出在我们新写的 FFM 代码中,这部分代码位于 Linux 内核的 GPIO 字符设备之上,通过原生调用与其通信。这可不是代码库中那种你会指望很快找到答案的部分。

于是,我把这个问题分配给了 Copilot 编码智能体,并提供了两个文件路径作为起点:提供程序类和 FFMDigitalInput。大约半小时后,一个拉取请求就提交了,其中的解释着实出乎我的意料。

每个输入都会运行一个事件监听器,阻塞在原生 poll() 调用中,等待内核报告其 GPIO 线路上的变化。这些监听器运行在虚拟线程中。而阻塞在原生调用内部的虚拟线程,无法从其载体线程上卸载。在整个调用期间,它都会被固定在那里。Raspberry Pi 4 有四个核心,因此虚拟线程调度器有四个载体线程。注册四个输入后,所有四个载体线程都会永远停在 poll() 中。第五个监听器虽然创建了,却始终得不到调度。这与报告中的缺陷完全吻合。不是“事件时灵时不灵”,而是“第五个完全没反应”。

我最欣赏的不是代码差异,而是随后在审查过程中展开的对话。我留了一条评论,请 Copilot 更详细地解释一下:

我以为虚拟线程的目标正是摆脱平台线程数量的限制?那么,在 Raspberry Pi 这样的四核处理器上,四个虚拟线程阻塞了四个线程,为什么就会成为问题呢?

完整对话请查看拉取请求。Copilot 能够将 Raspberry Pi 拥有四个 CPU 核心这一点与报告中的问题联系起来。它不仅提出了一个简单的修复方案,还提出了调查过程中发现的其他一些改进。

能分享一些技巧和最佳实践吗?

  • 告诉它去哪里找:针对 Pi4J 的 issue #622,我添加了两个文件路径。只需付出这点小小的努力,就能省去在大型代码库中进行的大量搜索。即使你对 bug 毫无头绪,通常也会隐约知道问题大概出在哪一块。把这个线索告诉工具,它就不必排查整个代码库了。
  • 要求提供证据和测试:“添加一个单元测试来验证这项修改”,是我最近经常提出的要求。准确地说,是以前经常提,因为现在它已经成了我指令文件中的一条规则。这也能避免误诊的情况,因为如果诊断有误,测试在旧代码上就不会失败。
  • 追问原因:如果你不理解某个修复方案,就直说并提问。解释也是交付成果的一部分,应该补充到项目文档、工单或拉取请求中。它能让之后阅读这些信息的每个人都学到东西。例如,这也引发了 Pi4J 团队内部关于原生调用中虚拟线程固定问题的更多讨论。
  • 保持掌控:Pi4J 中的所有这些拉取请求,在合并前都经过了维护者的审核和批准。这是最适合这个项目的模式:智能体负责调查,人类仍然对最终交付的内容负责。而在我的其他项目中,我也始终会审查工具生成的代码。我始终希望代码保持可读、可维护。工具经常会创建重复的方法,或者重新实现其他地方已有的功能,而这些本应整合起来。这是你的责任。如今,借助 AI 辅助编程,你可以推进得非常快,但这也意味着你可以非常快地制造出一团乱麻。别这么做,要让代码保持易于管理;如果同事和未来的你日后需要排查 bug 或进行改进,他们会感谢你的。

开始使用 GitHub Copilot >

文章《3 位 Java Champion 如何使用 GitHub Copilot 提升生产力》首发于 GitHub 博客。

来源:GitHub Blog · AI & ML · github.blog