zoukankan      html  css  js  c++  java
  • 代码只有0和1!??

     System.out.println相信这句话没有谁会陌生,但是你真的了解这句话吗?先来看看下面的代码:

    String s="abc"; 
        System.out.println(s); 
     s=null; 
        System.out.println(s);
    s="null"; 
        System.out.println(s);
    s=""; 
        System.out.println(s);
     s="  "; 
        System.out.println(s);

    看第二条和第三条:他们会输出什么呢???null?还是什么都没有?这个留给你们自己去验证看看。当然重要的不是结果。而是如果你认为是输出null那理由是什么呢?如果什么都不输出,理由又是什么呢?这时你可能会分析,s是空的,里面什么都没有,当然不会输出任何东西。又或者说s为null那么输出肯定就是null。不管是哪种想法(当然不只是这两种想法),是不是觉得思路一下子打开了呢?当然想法归想法,怎么验证我们的想法对不对呢?毕竟对于这样的一个程序来说结果是确定的。当然验证也很简单,跑一下这段代码就完了。那么答案出来了,但是我们前面的分析却并不是那么的严谨。那么如何才能更加合理的分析呢?其实有一个很简单的方式,那就是源代码。任何的东西在源代码面前都是透明。下面是println的源码:

     1 public void println(String x) {
     2         synchronized (this) {
     3             print(x);
     4             newLine();
     5         }
     6     }
     7  public void print(String s) {
     8         if (s == null) {
     9             s = "null";
    10         }
    11         write(s);
    12     }

    好了,结果已经很明显了。源代码已经把所有定西都告诉你了。那么把输出语句升级一下:

    JFrame jf=new JFrame();
    jf.setTitle("这是标题 ");        
    System.out.println(jf);
    
    Student a=new Student();
    System.out.println(a);

    这两句话又会输出什么咧?如果你的想法和我以前一样,脑子里马上冒出了“地址”二字,你怕是和我一样中毒已深咯。下面是这两句的输出结果:

    javax.swing.JFrame[frame0,0,0,0x0,invalid,hidden,layout=java.awt.BorderLayout,title=这是标题,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,0x0,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]
    com.cbs.Student@52cc8049

    那么在哪里看到了有地址这两个字呢?有人肯能会想第二句中的@52cc8049不是地址是什么?问题是你凭什么说它是地址呢?我说它是一串数字不行吗?或者它就是一串字符串。而且为何第一句和第二句的输出差别那么大呢?程序是不会骗人的,它既然输出了这样的结果,就意味着在代码的一句句的执行中,必然会存在这样的一句代码,造成了这样的输出结果。那么要找症结也就很容易了,只要找到那句输出的话就行了。还是上面的方法,源代码能够说明一切。

    //第一层源码
    public void println(Object x) {
            String s = String.valueOf(x);
            synchronized (this) {
                print(s);
                newLine();
            }
       }
    //第二层源码
    public static String valueOf(Object obj) {
            return (obj == null) ? "null" : obj.toString();
        }
    //第三层源码
     public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }

    好,现在先看第一层。可以看到String s是由valueOf这个方法的返回值决定的。所以在往上走,可以看到一个判断,如果传入的对象为空,那么返回字符串“null”,否则调用Object类的toString方法。但是到这里还是没有看到我们想看到的东西,那么继续往上走。找到Object的toString方法,好了终于找到了我们要输出的这句话了。先是类名然后@最后是加上的类的hashCode。这时你可看看上诉三个三个方法的注解,你会发现并没有哪里提到地址这个词。

    *Returns a string representation of the object. In general, the
    * {@code toString} method returns a string that
    * "textually represents" this object. The result should
    * be a concise but informative representation that is easy for a
    * person to read.
    * It is recommended that all subclasses override this method.

    这是toString方法注释的原话,显然并没有提过这里会输出对象的地址,只说过会得到一段hashCode。那么为什么第一句的输出又不一样呢?看注释的最后一句,我们都知道Java中的类都是Object类的子类,那么JFrame也不例外,所以说会不会是JFrame重写了toString方法呢?大家可以去找找JFrame的源码看看。现在你还认为打印对象输出的会是地址吗?那么终极一问,新建一A类的对象,下面的输出语句会输出什么(注意前提很重要!!)

    A a=new A();
    System.out.println(a);

    首先想到的会是什么?hashCode?一串字符?然而,我只想说,只要给我重写toString的机会,我可以输出整个世界!你想要什么?数字、界面、游戏.......或许程序的世界只有0和1,但是程序员却拥有整个世界。其实现在这个问题就跟问你:树上有八只鸟,开了一枪,那么树上还有几只鸟?是一样的了。

    瞎扯了半天,输出语句讲道理不就是输出吗?费的着在这研究那么久。我们都用过输出语句干嘛?单纯只是输出?有没有试过用它里排错。在编写代码的过程中,各种错误是无法避免的,遇到开发工具报错和异常的情况还好说,怕的就是编译没问题,但是始终的不到自己想要的结果。这时候就可以通过输出语句进行排错了。比如说:

    for (int c = 0; c < arry[0].length; c++) 
        for (int r = arry.length - 1; r >= 0; r--) 
            if (arry[r][c] == 0) 
                for (int r1 = r - 1; r1 >= 0; r1--) 
                    if (arry[r1][c] != 0) {
                        arry[r][c] = arry[r1][c];
                        arry[r1][c] = 0;
                        count++;                                
                        System.out.println("count: "+count);
                        break;
                        }

    这里的输出语句就能反映很多问题,if条件是否已经执行,如果执行了,那么count的值又会是多少?如果有很多的输出语句,给语句加上编号,就可以确定发生问题的位置。如果发现这一层的逻辑没有问题,可以考虑用输出继续检测上一层的语句。编程无非就是如此,出问题了排错,不懂了研究研究源码。能够做到这些,大部分的问题也就都不是问题了。

    ps:hashCode 数据结构中有哈希查找表的概念,实际上哈希表是通过一定的映射关系来确定元素的存储位置,来使得每个元素的平均查找长度尽可能的为0。哈希表的映射关系应该又叫哈希函数,hashCode并不一定就是地址,可能需要通过哈希函数来转换成元素的存储位置(地址)。

  • 相关阅读:
    Python操作Excel表格
    Python爬虫实战:爬取美食节川菜信息
    超级实用的Python网络爬虫反反爬策略之构造UA池及IP代理池
    Python 静态方法
    IDEA连接远程服务器Docker部署Spring Boot项目
    Dockerfile 解析
    Python爬虫实战-统计博客园阅读量问题
    Docker 容器数据卷
    Docker镜像
    PL/SQL
  • 原文地址:https://www.cnblogs.com/cbs-writing/p/7237128.html
Copyright © 2011-2022 走看看