zoukankan      html  css  js  c++  java
  • 你确定Java注释不会被执行吗?80%的人都不知道

    之前在博客上分享过一篇文章,涉及到 Java 中的注释,就信誓旦旦地写了一句话:“注释是不会被执行的!”结果,有小伙伴留言说,“老师,你确定吗?”

    我这个人一直有个优点,就是能听得进去别人的声音,管你是赞美的还是批评的,从来都是虚心接受。因为我相信,大多数小伙伴都是出于善的目的。

    况且,我在技术上从来没想过要成为多牛逼的大佬,就是喜欢分享的感觉,而已。很多文章中出现的错误,我都原封不动的保留,因为如果把修正了,那么留言中那些指出错误的人,在后来的读者眼里,就会觉得不合时宜。
    另外大家要注意光理论是不够的,记住:Java架构项目经验永远是核心,如果你没有最新JAVA架构实战教程及大厂30k+面试宝典,可以去小编的Java架构学习.裙 :七吧伞吧零而衣零伞 (数字的谐音)转换下可以找到了,里面很多新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 "u6c89u9ed8u738bu4e8c"
        ASTORE 1
       L1
        LINENUMBER 6 L1
        LDC "u6c89u9ed8u738bu4e09"
        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
    }
    复制代码

    嗯,表示看不懂。不过没关系,把它反编译一下就行了,于是我看到下面这段代码:

    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 的文件中:

    u0070u0075u0062u006cu0069u0063u0020u0020u0020u0020

    u0063u006cu0061u0073u0073u0020u0055u0067u006cu0079

    u007bu0070u0075u0062u006cu0069u0063u0020u0020u0020

    u0020u0020u0020u0020u0073u0074u0061u0074u0069u0063

    u0076u006fu0069u0064u0020u006du0061u0069u006eu0028

    u0053u0074u0072u0069u006eu0067u005bu005du0020u0020

    u0020u0020u0020u0020u0061u0072u0067u0073u0029u007b

    u0053u0079u0073u0074u0065u006du002eu006fu0075u0074

    u002eu0070u0072u0069u006eu0074u006cu006eu0028u0020

    u0022u0048u0065u006cu006cu006fu0020u0077u0022u002b

    u0022u006fu0072u006cu0064u0022u0029u003bu007du007d
    复制代码

    在命令行中先执行 javac Ugly.java,再执行 java Ugly 命令就可以看到程序结果了:

    Hello world
    复制代码

    体验过后,就拉到吧。反正写这样的代码谁也看不懂,除了机器。好了,我亲爱的读者朋友,以上就是本文的全部内容了。是不是感觉认知边界又拓宽了?
    最后注意:光理论是不够的,记住:Java架构项目经验永远是核心,如果你没有最新JAVA架构实战教程及大厂30k+面试宝典,可以去小编的Java架构学习.裙 :七吧伞吧零而衣零伞 (数字的谐音)转换下可以找到了,里面很多新JAVA架构项目教程,还可以跟老司机交流讨教! 

    本文的文字及图片来源于网络加上自己的想法,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理

  • 相关阅读:
    Opencv之像素值的获取
    亚像素级角点检测
    Shi-Tomasi角点检测
    卡尔曼滤波
    Harris角点检测理论
    ROS2GO 与WIN10 双系统安装
    数字集成电路物理设计学习总结——物理设计建库域验证
    跨时钟域信号传输(二)——数据信号篇
    跨时钟域信号传输(一)——控制信号篇
    亚稳态与多时钟切换
  • 原文地址:https://www.cnblogs.com/chengxuyuanaa/p/12838284.html
Copyright © 2011-2022 走看看