专栏首页码农UP2U一道有趣的 Java 基础题

一道有趣的 Java 基础题

问题

在一个 Java 群里有位群友分享了一道关于 Java 的题目,问代码是否抛异常。代码如下:

public class Hello {
    static String a, b;
    public static void main(String[] argc) {
        a = a + b;
        System.out.println(a);
    }
}

对于该问题,我只知道是不会抛出异常的,但是对于输出的结果我认为是空字符串。不知道大家是怎么考虑的。后来这位群友,给出的答案是不会抛出异常,输出的结果是 nullnull,且计算长度是 8 。感觉比较有意思,就自己分析了一下。

测试

在对这个结果产生兴趣时,我先进行了测试,将代码进行编译并运行,输出情况如下:

PS C:\Users\Administrator\Desktop> java Hello
nullnull

肉眼直接观察,输出的结果的确是 nullnul,而长度也肯定是 8。那么为什么呢?还是需要从 Java 的内部去进行了解。

分析

分析的最直接的方法应该是看 JDK 的源码,但是 JDK 的代码浩如烟海,不知从何看起。那么就直接看其反汇编代码。其反汇编代码如下:

 0: new           #2                  // class java/lang/StringBuilder
 3: dup
 4: invokespecial #3                  // Method java/lang/StringBuilder."<init>":()V
 7: getstatic     #4                  // Field a:Ljava/lang/String;
10: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
13: getstatic     #6                  // Field b:Ljava/lang/String;
16: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: putstatic     #4                  // Field a:Ljava/lang/String;
25: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
28: getstatic     #4                  // Field a:Ljava/lang/String;
31: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
34: return

我没有了解过 JVM 的指令,但是我了解过安卓 Dalvik 的 Smali 指令。两者在设计上虽然有所区别,但是实际还是比较相似的。不过本身这种虚拟机的指令抽象程度较高,也算是比较好理解。那么,这里我们就来看 StringBuilder 的 append 方法的源码(如果不看反汇编代码,我根本想不到这里要看的是 StringBuilder 类的 append 方法)。虽然,StringBuilder 有多个重载的 append 方法,但是根据反汇编指令也能够知道具体调用的是哪个方法。其源码如下:

@Override
public StringBuilder append(String str) {
    super.append(str);
    return this;
}

这里直接调用了其父类的方法,接着往上看它的代码,代码如下:

public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull();
    int len = str.length();
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
}

该代码在 AbstractStringBuilder 类中,通过上面的代码可以知道,当 str 为 null 时,会调用 appendNull 方法,该方法的代码如下:

private AbstractStringBuilder appendNull() {
    int c = count;
    ensureCapacityInternal(c + 4);
    final char[] value = this.value;
    value[c++] = 'n';
    value[c++] = 'u';
    value[c++] = 'l';
    value[c++] = 'l';
    count = c;
    return this;
}

从以上代码就不难看出,输出结果为什么是 nullnull 的情况了。

小结

这样的问题意义何在呢?我个人觉得,在项目中总会出现各种奇奇怪怪的问题,而一些奇奇怪怪的问题却是我们平时疏忽的基础或细节造成的,因此也在空闲之余,多多关注基础知识和技术细节,会有助于自己解决很多奇奇怪怪的问题。

本文分享自微信公众号 - 码农UP2U(gh_3c91b47a82e0),作者:码农UP2U

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-08-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 一道有趣的面试题

      前两天在刷leetcode的时候,遇到了一题Implement Rand10() Using Rand7(),rand7()可以给你等概率返回1-7的任意一...

    xindoo
  • javascript基础修炼(13)——记一道有趣的JS脑洞练习题

    console.log(i)在执行时,会按照词法作用域来取得循环条件中的变量 i的值,本题的基本思路实际上就是如何在console.log语句和for循环条件之...

    大史不说话
  • 一道有趣的Map迭代题

    神秘的寇先森
  • 一道有趣的树状数组题

    Every year, Farmer John's N (1 <= N <= 20,000) cows attend "MooFest",a social ga...

    ACM算法日常
  • 有趣又有用的一道前端面试题

    实现一个带并发限制的异步调度器 `Scheduler`,保证同时运行的任务最多有两个。完善下面代码中的 `Scheduler` 类,使得以下程序能正确输出。

    小小杨
  • 几道有趣的概率题

    昨晚睡觉前刷朋友圈,看到有朋友转了一篇叫做《和上帝一起掷骰子》的文章,里面提到了很多概率有关的问题,不少经过计算得出的概率都与人第一看上去产生的直觉大相径庭。所...

    Crossin先生
  • 【选择题】Java基础测试题一(10道)

    【选择题】Java基础测试题一(10道) 1.下面哪些是合法的变量名? (DEG) A.2variable //不能以数字开头 ...

    Java帮帮
  • 25道Java基础面试题

    如果值的范围在-128到127之间,它就从高速缓存返回实例。否则 new 一个Integer对象。new Integer 就是一个装箱的过程了,装箱的过程会创建...

    HaC
  • 【趣学程序】java基础知识(一)

    可以简单的理解为Java程序为了加强阅读行自定义的名称,如类名、方法名、变量名。仅仅是个名字而已。对于这样一个名字不像我们人类一样可以随意起名,程序有一定的命名...

    趣学程序-shaofeer
  • 一道有趣的笔试题(二)、降低功耗

    看到了一些interesting的题,和大家分享一下,如果大家有什么额外的见解欢迎大家公众号后台留言!

    根究FPGA
  • 一道有趣的笔试题(三)、锁存器Latch

    看到了一些interesting的题,和大家分享一下,如果大家有什么额外的见解欢迎大家公众号后台留言!

    根究FPGA
  • 一道有趣的笔试题(四)、序列检测

    看到了一些interesting的题,和大家分享一下,如果大家有什么额外的见解欢迎大家公众号后台留言!

    根究FPGA
  • 四道Java基础题,你能对几道?

    如果这道题你能得出正确答案,并能了解其中的原理的话。说明你基础还可以。如果你的答案 是 true 和true的话,你的基础就有所欠缺了。

    Java后端工程师
  • 用SQL解一道有趣的数学题:Gauss和Poincare

    杨廷琨,网名 yangtingkun 云和恩墨技术总监,Oracle ACE Director,ACOUG 核心专家 用SQL为解析一道数学题 ---- Ora...

    数据和云
  • 原创 | codeforces 1451D,一道有趣的博弈论问题

    今天选择的问题是Contest 1451场的D题,这是一道有趣简单的伪博弈论问题,全场通过的人有3203人。难度不太高,依旧以思维为主,坑不多,非常友好。

    TechFlow-承志
  • 一个有趣的问题

    前言   这个问题来自于看到的一个面试题,其中的解题过程比较有趣,有很多值得借鉴的地方,这里写出来作为记录。 题目 假设一栋100层的楼,两个完全一样的鸡蛋。...

    SecondWorld
  • 这道Java基础题真的有坑!我也没想到还有续集。

    自从我上次发了《这道Java基础题真的有坑!我求求你,认真思考后再回答。》这篇文章后。我通过这样的一个行文结构:

    why技术
  • Java的面试基础题(一)

    Java虚拟机是一个可执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。 Java被设计成允许应用程序可以运行在任意的...

    Demo_Yang
  • 【选择题】Java基础测试二(15道)

    【选择题】Java基础测试二(15道) 11.对于构造方法,下列叙述正确的是:(AC) A. 构造方法的方法名必须与类名相同; B. 构造方法必须用void...

    Java帮帮

扫码关注云+社区

领取腾讯云代金券