- 作者:老汪软件技巧
- 发表时间:2024-11-08 21:02
- 浏览量:
背景
看了一段项目源码,定义了一个 List 对象,但是往该列表对象 add 的代码前面有注释符号,但是程序运行时列表中却存在对象,为什么呢?仔细看了一下,注释符号和 add 代码之间有一个特殊符号 \u000d,这到底是什么东西呢?
奇怪的代码
public List getData() {
List data = new ArrayList<>();
for (int i = 0; i < 10; i++) {
// 注意,这里有个障眼法是 unicode 的换行符
// \u000d data.add(i);
}
logger.info("data count is {}", data.size());
return data;
}
运行结果:
基本原理
众所周不知「恕我孤陋寡闻,我没看过这种用法」,Java 编译器编译代码时会解析 unicode 字符,而代码中存在特殊字符的 unicode 符号时,就会产生障眼。
几个主要特殊符号:
\u000a 换行\u000d 回车\u007d 左花括号 {\u007b 右花括号 }启示录
想起刚入行的时候,看过一本电子书《疯狂的 Java 讲义》,书中介绍了很多 Java 的奇怪玩法,现在大部分都忘记了。
但对单例代码的漏洞,一直记忆犹新。即通过反序列化后创建的类可以打破单例,解决办法是重新序列化方法的 writeObject 保证也是单例。具体细节已经遗忘了,回忆了一下《序列化对单例模式的破坏》。
至于 Unicode 字符逃逸,项目中出现这类迷惑代码,普通开发怎么看得懂呢?尤其是我这种头脑比较简单的人,只会写简单代码,一见到复杂绕绕的代码就懵了哇!
话说回来,unicode 在某种场合还是有用的,比如绕过平台的敏感词检测,之前发布某篇文章通不过的时候,转换成 unicode 编码就过去了。作为程序员交流的暗语也是不错的!
\u8001\u733f\u4e0b\u73ed\u4e86