栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

java中的null到底是什么?

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java中的null到底是什么?

前言

无论从事什么职业,曾经在哪里工作,总要留下自己的一些痕迹。
也许是多年以后的某一天,你蓦然回首,你可以淡淡的说一句,来过!


一、null是什么?

我相信你肯定觉得这个问题很白痴,别着急,看代码:

public class NullClassTest {

    public static void sayHello() {
        System.out.println("hello");
    }

    public static void main(String[] args) {
        ((NullClassTest) null).sayHello();
        
        NullClassTest nullClassTest = null;
        nullClassTest.sayHello();
    }
}

请问以上代码编译能通过吗?如果通过了运行会报空指针异常吗?

别急我们接着往下看,打开NullClasTest的字节码:

 public static void main(java.lang.String[]);
   descriptor: ([Ljava/lang/String;)V
   flags: ACC_PUBLIC, ACC_STATIC
   Code:
     stack=1, locals=2, args_size=1
        0: aconst_null
        1: checkcast     #5                  // class com/myhexin/test/NullClasTest
        4: pop
        5: invokestatic  #6                  // Method sayHello:()V
        8: aconst_null
        9: astore_1
       10: aload_1
       11: pop
       12: invokestatic  #6                  // Method sayHello:()V
       15: return
     LineNumberTable:
       line 13: 0
       line 15: 8
       line 16: 10
       line 17: 15

我们看到第一个指令:aconst_null
通过查看虚拟机字节码指令表知道这条指令的含义是将null推送到栈顶,但是更多的信息就没有了,线索似乎到这里中断了。
别急,我们再看,我们知道Java是一门解释性语言(别杠,杠就是你对),虚拟机字节码指令需要解释器解释为机器指令才能执行。hotspot虚拟机中的zero解释器有这样一段代码:

	#define NULL 0
	...
	#define SET_STACK_OBJECT(value, offset) (*((oop *)&topOfStack[-(offset)]) = (value))
	...
      CASE(_aconst_null):
          SET_STACK_OBJECT(NULL, 0);
          UPDATE_PC_AND_TOS_AND_CONTINUE(1, 1);
      
      

SET_STACK_OBJECT(NULL, 0)代码的含义是将栈中偏移量为0的位置的值设为0.
所有在内存中null的值其实是零。这似乎跟我们猜想的不太一样他怎么会是0呢?
0的含义是什么?我们知道java的宿主语言是C++,那么C++中会不会有我们想要得答案呢?
恰巧博主在学习C++的过程中看到过一段话:

原来0代表不指向任何一个可访问的地址。
那么我们开局的代码运行结果是什么呢?根据上边我们一步一步的推导你肯定在想爱,是报空指针啦!
错,错,错!
通过程序运行:

不仅没报错反而正确运行了。null不是指向不指向任何可访问的地址吗?这怎么还调用成功了呢?
其实呢这一切的一切都是编译器在作怪,我们用ide工具打开编译后的class文件,当然牛逼的可以直接看字节码指令,但是通过ide查看会更直观:

public class NullClassTest {
    public NullClassTest() {
    }

    public static void sayHello() {
        System.out.println("hello");
    }

    public static void main(String[] args) {
        NullClassTest var10000 = (NullClassTest)null;
        sayHello();
        NullClassTest nullClassTest = null;
        sayHello();
    }

开具的代码经过编译器的处理变成了以上的形式,其实是编译器偷偷改了我们的代码,他替我们写了正确的调用方法。
以上就是就是Java中的null,觉得有帮助的可以点个赞。
ps:zero解释器的代码路径:hotspot源码下的srcsharevminterpreterbytecodeInterpreter.cpp

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/994768.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号