Tips: 本期食用语言:JvavJava
零、闲聊
当我在想如何更简单地将编码转换为Unicode时看到了一篇文章,直接给我 CPU 干烧了,转义字符还能这样用?!
以前写 C++ 的时候就尝试过将四位十六进制直接转换成宽字符类型(即 wchar_t
类型),但最终都没有达成目标。C++ 就是喜欢抓着 ANSI 不放,虽然办法不是没有,但都太麻烦了。绝对不是我懒
一、代码
先来看看下面这段代码:
public static void main(String[] args) {
String a = "Hello";
// \u000d a="world";
System.out.println(a);
// \u000a a="hello world!";
System.out.println(a);
}
这段代码来自前文的一篇文章里的一篇文章,看似十分普通,会输出两遍 Hello
,但现实却令人大跌眼镜:
输出:
world
hello world!
说好的
Hello
呢?
再来看看下面这段代码:
\u0009\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0073\u0074\u0061\u0074\u0069\u0063\u0020\u0076\u006f\u0069\u0064\u0020\u006d\u0061\u0069\u006e\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u005b\u005d\u0020\u0061\u0072\u0067\u0073\u0029\u0020\u007b
\u0009\u0009
\u0009\u0009\u0053\u0074\u0072\u0069\u006e\u0067\u0020\u0061\u0020\u003d\u0020\u0022\u0048\u0065\u006c\u006c\u006f\u002c\u0020\u0077\u006f\u0072\u006c\u0064\u0021\u0022\u003b\u0020
\u0009\u0009\u0053\u0079\u0073\u0074\u0065\u006d\u002e\u006f\u0075\u0074\u002e\u0070\u0072\u0069\u006e\u0074\u006c\u006e\u0028\u0061\u0029\u003b\u0020
\u0009\u007d
是不是感觉要长脑子了?
根本不知道在写什么!
然而,把它代替原本的主函数,竟然还能运行?!
输出:
Hello, world!
二、原理
应该也有不少人看出来了,这不就是 Unicode 吗?至少也得知道这些都是两个字节的十六进制吧
事实上,雀食如此。
java 对这些 Unicode 编码先进行了一遍解码,然后再投给 jdk 进行进一步转换。具体流程本蒟蒻也不懂
可以发现,将生成的 class 文件进行反编译之后就能看懂了。
反编译之后的程序:
public static void main(String[] var0) {
String var1 = "Hello, world!";
System.out.println(var1);
}
而这些 Unicode 编码,事实上是通过转义字符 \u
来表示的。
而 Java 的 \u
转义字符可以写在非字符/字符串的地方,可以粗略理解为 Java 自带的宏定义。
例如:\u0020
是空格,\u0061
是 a
。
在最开始的代码里,\u000d
和 \u000a
分别代表回车和换行。
注意,回车和换行是有区别的。回车是跳转到一行的开始,换行是向下移动一格(行)。在 Windows 操作系统下,Enter 键实际上是回车和换行的结合体。
Tips:回车(\r),换行(\n)
然鹅,Java 会把 \r
当成 \r\n
,具体本蒟蒻也不懂,稍微写得好理解点,代码变成了这样:
public static void main(String[] args) {
String a = "Hello";
//
a="world";
System.out.println(a);
//
a="hello world!";
System.out.println(a);
}
看似是注释的那一段跳到了下一行,就不再是注释了。如果在项目里面这样写,下一位是不是要疯掉
三、拓展
Java常见转义字符一览表
----------我是分界线----------
Tips:在前 128 位(0~127),Unicode 和 ASCII 对应字符完全相同。
转义字符 | 意义 | ASCII 码 (十六进制) |
---|---|---|
\??? | 三位八进制数 | 三位八进制对应字符 |
\0 | 空字符 (NULL) | 0x00 |
\a | 响铃 (BEL) | 0x07 |
\b | 退格 (BS,将当前位置移到前一列) | 0x08 |
\f | 换页 (FF,将当前位置移到下页开头) | 0x0c |
\n | 换行 (LF,,将当前位置移到写一行开头) | 0x0a |
\r | 回车 (CR,将当前位置移到本行开头) | 0x0d |
\t | 水平制表 (HT,相当于 TAB 键) | 0x09 |
\u | Unicode 编码对应字符 | 无 |
\v | 垂直制表 (VT) | 0x0b |
\ | 字符 \ | 0x5c |
’ | 字符 ' | 0x27 |
" | 字符 " | 0x22 |
? | 字符 ? | 0x3f |
看中间那列的形状是不是很像一个爱心权杖
THE END
Tips:文章一个彩蛋你找到了吗?找到了千万别发评论区 找到了点个赞就行!
- 别忘了点赞收藏关注!
- 结束了!
- 如文章有误可以私信或发在评论区
- 真的结束了!!
这下不骗你,结束! \small\color{white}这下不骗你,结束! 这下不骗你,结束!