之前在博客上分享过一篇文章,涉及到 Java 中的注释,就信誓旦旦地写了一句话:“注释是不会被执行的!”效果,有小伙伴留言说,“先生,你确定吗?”
我这小我私家一直有个优点,就是能听得进去别人的声音,管你是赞美的照样指斥的,从来都是虚心接受。由于我信赖,大多数小伙伴都是出于善的目的。
况且,我在技术上从来没想过要成为多牛逼的大佬,就是喜欢分享的感受,而已。许多文章中泛起的错误,我都原封不动的保留,由于若是把修正了,那么留言中那些指出错误的人,在厥后的读者眼里,就会以为不合时宜。
那些 diss 我的小伙伴们,放心,我是不会介意的。
尽管如此,但对于注释这件事,真的是不能忍啊!注释一定不会被执行啊,我想这位小伙伴一定是在取笑我。于是我就私信问他为什么,然后他就甩给了我下面这段代码:
public class Test {
public static void main(String[] args) {
String name = "缄默王二";
// \u000dname="缄默王三";
System.out.println(name);
}
}
我拷贝到 IDEA 中跑了一下,效果程序输出的效果出乎我的意料:
缄默王三
竟然是王三,不是王二。看到这个效果,我算是彻底懵逼了。
那一刹那,我感受这十来年的 Java 算是白学了。大学那会,先生说注释是不会执行的;就连《编程头脑》里也说注释是不会执行的。那现在谁能告诉我这到底为什么?
不是说程序的天下很单纯吗?不是 0 就是 1?事情搞到这个境界,只能花心思好好研究一下了。
单纯从代码上来看,问题应该出在那串特殊的字符上——\u000d
,若是不是它在作怪,把 name 的值由“缄默王二”修改为了“缄默王三”,就没有其余缘故原由了——没其余,依附多年的工作经验,找问题的泉源我照样很轻车熟路的。
\u000d
虽然看上去对照生疏,但我知道它是一个 Unicode 字符。问了一下搜索引擎后,知道它代表一个换行符——一种名顿开的感受啊。我知道,Java 编译器不仅会编译代码,还会剖析 Unicode 字符。
我大致看了一眼上面这段代码编译后的字节码,它长下面这个样子:
// class version 58.65535 (-65478)
// access flags 0x21
public class com/cmower/dzone/secret/Test {
// compiled from: Test.java
// access flags 0x1
public <init>()V
L0
LINENUMBER 3 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this Lcom/cmower/dzone/secret/Test; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x9
public static main([Ljava/lang/String;)V
L0
LINENUMBER 5 L0
LDC "\u6c89\u9ed8\u738b\u4e8c"
ASTORE 1
L1
LINENUMBER 6 L1
LDC "\u6c89\u9ed8\u738b\u4e09"
ASTORE 1
L2
LINENUMBER 7 L2
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ALOAD 1
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L3
LINENUMBER 8 L3
RETURN
L4
LOCALVARIABLE args [Ljava/lang/String; L0 L4 0
LOCALVARIABLE name Ljava/lang/String; L1 L4 1
MAXSTACK = 2
MAXLOCALS = 2
}
嗯,示意看不懂。不外没关系,把它反编译一下就行了,于是我看到下面这段代码:
Linux安装maven(详细教程)
public class Test {
public Test() {
}
public static void main(String[] args) {
String name = "缄默王二";
name = "缄默王三";
System.out.println(name);
}
}
咦,两个反斜杠 //
真的不见了,这可以确定一点——注释确实是不会执行的。只不外 \u000d
把 name="缄默王三";
挤到了 //
注释的下一行,就似乎下面这段代码的样子:
public class Test {
public static void main(String[] args) {
String name = "缄默王二";
//
name="缄默王三";
System.out.println(name);
}
}
那这算不算是 Java 的 bug 呢?说算也不算。
由于通过允许 Java 源代码包罗 Unicode 字符,可以确保在天下上任何一个区域编写的代码在其他地方执行。
老实说,这段话是我从网上找到,似乎明白点啥,又似乎不明白。那再来看一段代码:
double π = Math.PI;
System.out.println(\u03C0);
假如说程序员小王在建立周期率这个变量的时刻,不知道 π
这个字符怎么敲出来,那么他就可以选择使用 \u03C0
来替换——编译器知道 \u03C0
就是 π
这个变量(编译器会在编译其他代码之前先剖析 Unicode 字符)。
只能说 \u000d
是一种破例吧。
固然了,除非特殊情况,不要在源代码中包罗 Unicode 字符,以免更改源代码的本意。
这篇文章没有其余意思,我也不想探讨过于深奥的器械,纯粹是提高一下小伙伴们的认知:注释有可能被编译器执行。就似乎,鲁迅若是不知道茴香豆的“茴”字有 4 种写法,那他就没办法让孔乙己在鲁镇的那家茶馆里装逼。
固然了,若是有小伙伴想体验一下装逼的感受的话,可以把下面这段代码保存在一个名叫 Ugly.java 的文件中:
\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0020\u0020\u0020
\u0063\u006c\u0061\u0073\u0073\u0020\u0055\u0067\u006c\u0079
\u007b\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0020\u0020
\u0020\u0020\u0020\u0020\u0073\u0074\u0061\u0074\u0069\u0063
\u0076\u006f\u0069\u0064\u0020\u006d\u0061\u0069\u006e\u0028
\u0053\u0074\u0072\u0069\u006e\u0067\u005b\u005d\u0020\u0020
\u0020\u0020\u0020\u0020\u0061\u0072\u0067\u0073\u0029\u007b
\u0053\u0079\u0073\u0074\u0065\u006d\u002e\u006f\u0075\u0074
\u002e\u0070\u0072\u0069\u006e\u0074\u006c\u006e\u0028\u0020
\u0022\u0048\u0065\u006c\u006c\u006f\u0020\u0077\u0022\u002b
\u0022\u006f\u0072\u006c\u0064\u0022\u0029\u003b\u007d\u007d
在下令行中先执行 javac Ugly.java
,再执行 java Ugly
下令就可以看到程序效果了:
Hello world
体验事后,就拉到吧。横竖写这样的代码谁也看不懂,除了机械。好了,我亲爱的读者同伙,以上就是本文的全部内容了。是不是感受认知界限又拓宽了?
我是缄默王二,一枚有趣的程序员。若是以为文章对你有点辅助,请微信搜索「 缄默王二 」第一时间阅读,回复【666】更有我为你经心准备的 500G 高清教学视频(已分门别类)。
本文 GitHub 已经收录,有大厂面试完整考点,迎接 Star。
原创不易,莫要白票,请你为本文点个赞吧,这将是我写作更多优质文章的最强动力。
原创文章,作者:28x29新闻网,如若转载,请注明出处:https://www.28x29.com/archives/7299.html