关于我对 [ 一段很有意思的代码 ] 一文有些疑问这件事


前言

闲暇之余, 抱着学习(好奇)的心态去看了这样一篇文章 一段很有意思的代码!!
这是由我最尊敬(指每次遇到比较系统的问题都会去这里学习, 一日为师下句我就不说了~)的公众号 [ 菜鸟教程 ] 转载的
业内分布式技术大佬 [ 冰河 ] 原创的一篇文章. 原文找了半天没看到, 不清楚这个疑问是否有人已经提出.
因此我就斗胆的提出我的拙见~ 如有问题欢迎大家指出. 鄙人在此抱拳~~~

在这里插入图片描述


一、原文简介

  1. 本文对以下代码在调用 print 方法后, 同时执行了 ifelse 分支进行分析, 代码和输出结果如下图所示:

    public class Test {
          
          
    
        public static void main(String[] args) {
          
          
        	// 核心代码
            new Test().print(args==null || new Test() {
          
          {
          
          Test.main(null);}}.equals(null));
        }
    
        public void print(boolean flag){
          
          
            if(flag){
          
          
                System.out.println("我是if语句的分支");
            }else{
          
          
                System.out.println("我是else语句的分支");
            }
        }
    }
    

    在这里插入图片描述

  2. 原作者文中说法可简述为,:
    在 || 前 args == null 为 true,执行 print() 方法的 if 语句.
    后面因为再次创建了一个 Test 类的对象实例(不为null), 因此 equals((Object)null) 为 false , 执行 print() 方法 else语句

  3. 通过留言来看, 大多说人都把作者的描述理解为 || 前面为 true 后, 又继续执行后面的
    那么事实真是如此吗?, 看到这里, 我眉头一皱发现事情并不简单
    在这里插入图片描述

  4. 其实, 仔细阅读后你就会发现, 作者的本意不是如此. 因为文中强调 main 方法执行了两次
    因此, 综合来看, 作者的意思实际是: 第一次执行 main 时, args == null 为 true , 执行 print() 方法的 if 语句,
    然后第二次执行main 时, equals((Object)null) 会返回 false, 执行了 else 语句的逻辑

二、分析

那么? 事情真的如作者说的那样? 出于一种奇怪的本能我发现事情并没有这么简单
于是, 带着疑问我们来对代码动点小手术, 加两行打印语句, 看下执行结果

1.改造代码, 增加信息打印

    public static void main(String[] args) {
    
    
    	// 判断 args == null 的结果情况
        System.out.println(args == null);
        new Test().print(args==null || new Test() {
    
    
            {
    
    
                System.out.println("第二层main()执行开始" );
                Test.main(null);
                System.out.println("第二层main()执行结束" );
            }
        }.equals(null));
    }
    public void print(boolean flag){
    
    
        if(flag){
    
    
            System.out.println("我是if语句的分支");
        }else{
    
    
            System.out.println("我是else语句的分支");
        }
    }

代码运行结果
在这里插入图片描述

2.分析

  1. 可以看到, 第一次运行时, main函数入参 args == null 是false !

  2. 为什么 为false ? 这就考察我们 == 的含义这个知识点了
    在基本数据类型时 == 比较的是值, 而在对象或其他类型中比较的是引用地址
    因为在函数声明时已经定义好 args 数组并在堆内存中开辟空间建立历引用(相当于初始化), 因此 args == null结果为false

  3. 我们在把核心代码 new Test().print(args==null || new Test() { {Test.main(null);}}.equals(null));
    优化成 new Test().print(A || B); , 所以在第一次执行外层main方法时, A = args == null = false,
    由于 || 代表短路或, 只有 || 前后都为false 才返回 false, 而如果 || 前为 false 为 false 时会继续判断后面的语句
    在本代码中相当于继续执行B代码块

  4. 执行B代码块后, 相当于在main方法中再次调用了一次 main 方法
    在第二次 main 中通过类名.静态方法来调用main方法, 并且传参null. 这相当于强制令数组等于null,
    因此在执行第二次main方法中, new Test().print(A || B); A代码块为true,
    因为 || 代表短路或, 遇到true会直接返回, 所以会直接执行print方法的if语句

  5. 执行玩第二次main方法后, 第一次 main 方法也执行完毕, 由下图图可知 B 永远为 false
    因此在第一次main方法的核心代码 new Test().print(A || B)中 false || false 结果为 false , 所以才会执行else 语句!
    在这里插入图片描述

3. 总结

第一次运行main 方法时, 核心代码 new Test().print(A || B); 因为 A 代码块为 false 因此执行 B 代码块
但在B代码块中又调用了一次main方法并且为main方法设置入参,
导致没有执行完第一次main 方法的 B代码块前又执行第二次main 方法, 它的核心代码也是 new Test().print(A || B);,
并且 A为true, 因为短路或遇到 true 会直接返回 true, 因此首先执行 print 方法的 if 语句
然后将第一次 main 方法的 B 代码块执行完毕(false), 同时因为 A = false, A || B 为 false, 因此执行 print 方法的 else 语句


三、体会

  1. 通过对一个问题的探究巩固了很多知识点
    比如: 短路或的使用, == 的含义, 函数以及形参在内存中的模型等等
  2. 对于感到兴趣或者疑问的问题, 不妨多动手试试, 或许有意想不到的结果
  3. 夏天到了, 一曲 冰柜 送上

猜你喜欢

转载自blog.csdn.net/qq_43371556/article/details/124879701