Day 9.Java字符运算与字符串拼接 多流程数字员工开发的尝试
今日
一、字符 char 运算(基础)
- char 底层本质
char 是16 位无符号整数,存储 Unicode 编码值(0~65535),本质是数字,可以参与算术运算、比较运算。
char c = 'A';
System.out.println(c + 0); // 输出65,'A'的ASCII码 - 字符算术运算规则
char + 数字 = int:运算时 char 自动提升为 int,结果一定是整型
char a = '1';
int res = a - '0'; // '1'编码49,'0'编码48 → 结果1(字符转数字常用写法)
char b = 'a';
System.out.println(b + 32); // 'a'=97,大写'A'=65,大小写差32
char + char = int:两个字符相加,都转编码值求和,输出数字
System.out.println('A' + 'B'); // 65+66=131
自增 / 自减不升 int:char++ / char-- 可直接修改字符,不用强转
char ch = 'z';
ch++;
System.out.println(ch); // '{'
减法常用场景:数字字符转真实数值
'5' - '0' = 5,大小写转换 c - 32(小写转大写)、c + 32(大写转小写) - 字符比较运算
直接用 > < == >= <=,底层对比 Unicode 编码大小:
System.out.println('a' > 'A'); // true(97>65)
System.out.println('9' > '0'); // true
二、字符串 String 拼接(核心重点) - 拼接运算符 + 规则(优先级从左到右)
规则 1:只要一侧是 String,+ 就是拼接,结果为 String
从左向右依次计算,遇到字符串后,后续全部转为字符串拼接
// 案例1:数字在前,字符串在后
System.out.println(10 + 20 + "abc"); // 先算10+20=30 → "30abc"
// 案例2:字符串在前,全部拼接
System.out.println("abc" + 10 + 20); // "abc1020"
// 案例3:字符参与
System.out.println('A' + "test" + 1); // "Atest1"
规则 2:纯数字 / 字符之间的 + 是数学加法,不是拼接
无字符串时,char、byte、short、int 全部做算术运算。 - 字符串拼接底层原理(常量池 vs 堆)
(1)常量字符串直接拼接:编译期优化
String s1 = "a" + "b" + "c";
// 编译时直接优化为 String s1 = "abc";
// 只在字符串常量池创建1个对象,无中间垃圾
特点:全部是双引号字面量,编译器直接合并,性能极高。
(2)含变量的拼接:运行时创建 StringBuilder
String a = "a";
String s2 = a + "bc";
// 等价底层代码:
String s2 = new StringBuilder(a).append("bc").toString();
JDK1.5+ 所有带变量的 + 拼接,底层自动用 StringBuilder
循环内频繁 str += x 会反复创建 StringBuilder,性能差,建议手动创建 - 三种拼接方式对比
方式 原理 适用场景 性能
- 运算符 常量编译优化;变量自动封装 StringBuilder 少量零散拼接、简单代码 少量字符串快,循环大量拼接 差
StringBuilder.append() 可变字符数组,无中间对象 循环、大量字符串拼接 最优
StringBuffer.append() 加同步锁线程安全 多线程并发拼接 略慢于 StringBuilder
- 特殊拼接陷阱
空字符串拼接任意类型,自动调用 toString ()
String str = null + ""; // "null",不会空指针
null 变量拼接不会抛 NPE,会转为字符串 "null"
字符 / 数字和字符串混合时,区分运算顺序:
System.out.println(1 + 'A' + ""); // 66
System.out.println("" + 1 + 'A'); // "1A" - 字符串常量池关键补充
String s1 = "java";
String s2 = "ja" + "va";
System.out.println(s1 == s2); // true,编译优化同一常量池对象
String a = "ja";
String s3 = a + "va";
System.out.println(s1 == s3); // false,s3在堆中新创建对象
流程数字员工的开发思路
5 个核心组件
- 协调器(Coordinator) — 消息进来后先过这一层
不用写规则判断,而是调一次 GLM,让它分析用户意图,返回该激活哪些角色:
用户:"我要做一个在线商城系统"
→ 协调器调GLM:"分析这条消息,判断需要哪些角色参与"
→ GLM返回:["项目经理", "开发工程师", "测试工程师"]
2. 角色 Agent — 每个角色有独立的 system prompt
每个 Agent 本质上就是一次 call_glm() 调用,区别只是 system prompt 不同:
角色 system prompt 核心内容
项目经理 "你是项目经理,负责需求分析、任务拆分、工期评估、风险评估"
开发工程师 "你是高级开发工程师,负责技术选型、架构设计、接口定义、代码评审"
测试工程师 "你是测试工程师,关注边界条件、异常路径、性能测试、质量评估"
运维工程师 "你是DevOps工程师,负责部署方案、CI/CD流水线、监控告警、容灾"
3. 角色间通信 — Agent 可以互相"说话"
协调器激活角色后,不是各干各的,而是串行传递:
PM Agent 分析需求 → 把结果传给 Dev Agent
→ Dev Agent 根据PM的需求设计架构 → 把结果传给 QA Agent
→ QA Agent 根据架构写测试用例
虚线箭头就是这个——角色间可以传递上下文,不是完全隔离的。
- 汇总器(Aggregator) — 合并所有角色的输出
各角色完成后,再调一次 GLM,让它把多个角色的回复整理成一份结构化报告:
输入:
PM的输出:需求拆分为5个模块...
Dev的输出:技术方案采用React+Node.js...
QA的输出:测试覆盖登录、支付、库存...
输出(汇总器整理):
📋 需求分析:...
💻 技术方案:...
🧪 测试计划:...
📦 部署建议:...
5. 状态管理 — 跟踪工作流进度
需要记住当前对话到了哪一步(需求分析→技术设计→开发→测试→部署),这样用户可以追问"下一步呢"。
具体工作流示例
用户发消息:帮我规划一个在线商城系统
第1步:协调器 → GLM判断 → 激活 [PM, Dev, QA]
第2步:PM Agent → "需求拆分为:用户模块、商品模块、订单模块、支付模块、后台管理"
第3步:PM输出 → 传给 Dev Agent
第4步:Dev Agent → "技术栈:前端React,后端Node.js,数据库MySQL+Redis,支付对接微信/支付宝"
第5步:Dev输出 → 传给 QA Agent
第6步:QA Agent → "测试要点:登录边界、支付并发、库存超卖、SQL注入防护"
第7步:汇总器 → 合并3个角色输出 → 结构化回复用户

明日
继续学习Java,开发流程数字员工
问题及解决方案
char + char 是数字加法,不是拼接;只有一侧有字符串才是拼接
表达式从左到右执行,字符串出现前后结果完全不同
循环中禁止 String +=,推荐手动 StringBuilder
字符转数字固定公式:数字字符 - '0'
字面量全常量拼接编译优化,含变量拼接运行时 new StringBuilder
char 自增不用强转,char 参与四则运算会自动提升为 int
null 和字符串拼接输出 "null",不会空指针异常

浙公网安备 33010602011771号