char数组可安全存储原始文本和密文,因char是16位unicode码点;加密宜原地操作char[]避免string拼接与编码问题;caesar加密需区分大小写并用模运算绕回字母边界。

char 数组怎么存原始文本和密文
Java 中 char 是 16 位无符号整数,直接对应 Unicode 码点,所以 char[] 能安全存字母、数字、常见符号,也支持中文(如 '中' 是合法的)。加密时别用 String 拼接,避免创建多余对象;用 char[] 原地修改更可控,也方便后续清空敏感内容。
常见错误:把加密结果转成 String 后再转回 char[] —— 这多此一举,还可能因编码问题丢字符(比如某些代理对)。
- 初始化用
char[] text = "hello".toCharArray(); - 密文数组大小和原文一致:
char[] cipher = new char[text.length]; - 别直接
char[] cipher = text;—— 这是引用复制,改 cipher 就等于改原文
用 for 循环对每个 char 做位移加密(Caesar)
最简可行方案就是 Caesar 加密:每个字符 ASCII 码加一个固定偏移量。注意只处理字母,数字和符号保持原样,否则解密会乱。
关键判断逻辑在循环体内:先区分大小写,再计算新字符是否越界('z' + 1 不能是 '{'),要用模运算绕回。
int shift = 3; for (int i = 0; i = 'a' && c = 'A' && c
- 偏移量
shift建议用 final 变量或常量,避免魔法数字 -
% 26保证结果始终落在字母范围内,不用 if 判断上下界 - 别对非字母调
Character.isLetter()再强转 —— 它返回 true 的字符不一定能被char安全表示(比如某些增补字符)
为什么不能直接用 += 或 ++ 修改 char 数组元素
写 text[i] += shift; 看似简洁,但 Java 会隐式将 char 提升为 int 计算,再强制转回 char。这会导致非预期结果:比如 'z' += 1 得到 '{'(ASCII 123),而不是想要的 'a'。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
更隐蔽的问题是中文字符:若误对 '中'(Unicode U+4E2D)做 += 3,得到的是另一个汉字(U+4E30),但解密时无法可靠还原 —— 因为中文不是连续编码的字母表。
- 必须显式判断范围再计算,不能依赖算术溢出自动绕回
- 所有修改都应基于已知字符集(如仅 a–z/A–Z/0–9)设计规则
- 如果真要支持 Unicode 全集,得用
codePointAt()+Character.toChars(),但那就不是“简单加密”了
解密时容易漏掉的细节
解密不是简单把 shift 换成负数再套一遍 —— (c - 'a' - shift) % 26 在 shift 大于当前值时会得负数,比如 ('a' - 'a' - 5) % 26 == -5,不是 21。
正确做法是加 26 再取模:(c - 'a' - shift + 26) % 26,确保结果非负。
- 加法和减法的模运算不对称,这是最容易翻车的地方
- 建议把加解密逻辑封装成两个独立方法,别共用同一段循环体
- 测试用例至少覆盖边界:如
"xyz"加密后是"abc",再解密必须回到"xyz"
真正麻烦的从来不是写循环,而是确认每个字符的映射是否可逆、是否覆盖全部输入可能。一旦接受用户任意输入,就得提前定义好哪些字符允许加密、哪些跳过、哪些报错 —— 这部分逻辑比位移本身重得多。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










