前言

在java中初始化的时候经常用到null,也经常会碰到空指针异常(NullPointerException),由于碰到的频率比较高,我认为有必要进行一下了解,揭开它的神秘面纱。

一、null是代表不确定的对象

Java中,null是一个关键字,用来标识一个不确定的对象。因此可以将null赋给引用类型变量,但不可以将null赋给基本类型变量。

比如:int a = null;是错误的。Ojbect o = null是正确的。

Java中,变量的适用都遵循一个原则,先定义,并且初始化后,才可以使用。我们不能int a后,不给a指定值,就去打印a的值。这条对对于引用类型变量也是适用的。

有时候,我们定义一个引用类型变量,在刚开始的时候,无法给出一个确定的值,但是不指定值,程序可能会在try语句块中初始化值。这时候,我们下面使用变量的时候就会报错。这时候,可以先给变量指定一个null值,问题就解决了。例如:

        Connection conn = null;

        try {

            conn = DriverManager.getConnection("url", "user", "password");

        } catch (SQLException e) {

            e.printStackTrace();

        }

        

        String catalog = conn.getCatalog();

如果刚开始的时候不指定conn = null,则最后一句编译器会认为这个对象没有初始化,就会报错。

二、null本身既不是一种类型,也不是一个对象

null本身虽然能代表一个不确定的对象,但就null本身来说,它不是对象,也不知道什么类型,也不是java.lang.Object的实例。

可以做一个简单的例子:

        // null是对象吗? 属于Object类型吗?

        if (null
instanceof java.lang.Object) {

            System.out.println("null属于java.lang.Object类型");

        } else {

            System.out.println("null不属于java.lang.Object类型");

        }

结果会输出:null不属于java.lang.Object类型。

null不属于java.lang.Object类型

 

有趣的是:

        Integer iAmNull = null;

        if (iAmNull
instanceof Integer) {

            System.out.println("iAmNull is instance of Integer");

 

        } else {

            System.out.println("iAmNull is NOT an instance of Integer");

        }

结果输出:

iAmNull is NOT an instance of Integer

即:当对象初始化为null时,它只是null,并不是这个类的实例。

 

初始化为null和未初始化的区别:

调用方法时的报错不同,一个是运行时异常,即空指针异常;一个编译时异常。

 

同时你也可以将null转成任意类型。

        String str = null; // null can be assigned to String

        Integer
itr = null; // you can assign null to Integer also

        Double dbl = null; // null can also be assigned to Double

 

        String myStr = (String) null; // null can be type cast to String

        Integer
myItr = (Integer) null; // it can also be type casted to Integer

        Double myDbl = (Double) null; // yes it's possible, no error

可以看到在编译和运行时期,将null强制转换成任何引用类型都是可行的,在运行时期都不会抛出空指针异常。

但是也没看出来这种强转有任何意义。

三、Java默认给引用类型变量赋值null

在定义变量的时候,如果定义后没有给变量赋值,则Java在运行时会自动给变量赋值。赋值原则是整数类型int、byte、short、long的自动赋值为0,带小数点的float、double自动赋值为0.0,boolean的自动赋值为false,其他各供引用类型变量自动赋值为null。

这个具体可以通过调试来看。

四、容器类型与null

List:允许重复元素,可以加入任意多个null。

Set:不允许重复元素,最多可以加入一个null。

Map:Map的key最多可以加入一个null,value字段没有限制。

数组:基本类型数组,定义后,如果不给定初始值,则java运行时会自动给定值。引用类型数组,不给定初始值,则所有的元素值为null。

五、可以使用静态方法来使用一个值为null的引用类型变量

你可能知道不能调用非静态方法来使用一个值为null的引用类型变量。它将会抛出空指针异常,但是你可能不知道,你可以使用静态方法来使用一个值为null的引用类型变量。因为静态方法使用静态绑定,不会抛出空指针异常。下面是一个例子:

    public
static
void main(String args[]) {

        Test1
myObject = null;

        myObject.iAmStaticMethod();

        myObject.iAmNonStaticMethod();

    }

 

    private
static
void iAmStaticMethod() {

        System.out.println("I am static method, can be called by null reference");

    }

 

    private
void iAmNonStaticMethod() {

        System.out.println("I am NON static method, don't date to call me by null");

    }

结果输出:

I am static method, can be called by null reference

Exception in thread "main" java.lang.NullPointerException

    at test._null.Test1.main(Test1.java:58)

六、
可以使用==或者!=操作来比较null值

你可以使用==或者!=操作来比较null值,但是不能使用其他算法或者逻辑操作,例如小于或者大于。跟SQL不一样,在Java中null==null将返回true,如下所示:

String
abc = null;

        String
cde = null;

 

        if (abc == cde) {

            System.out.println("null == null is true in Java");

        }

 

        if (null != null) {

            System.out.println("null != null is false in Java");

        }

 

        // classical null check

        if (abc == null) {

            // do something

        }

 

        // not ok, compile time error

        /*if (abc > null) {

 

        }*/

结果输出:

null == null is true in Java

 

 

参考文献:

深入Java关键字null

Java中有关Null的9件事

 

详解null的更多相关文章

  1. 深入详解SQL中的Null

    深入详解SQL中的Null NULL 在计算机和编程世界中表示的是未知,不确定.虽然中文翻译为 “空”, 但此空(null)非彼空(empty). Null表示的是一种未知状态,未来状态,比如小明兜里 ...

  2. 为什么说JAVA中要慎重使用继承 C# 语言历史版本特性(C# 1.0到C# 8.0汇总) SQL Server事务 事务日志 SQL Server 锁详解 软件架构之 23种设计模式 Oracle与Sqlserver:Order by NULL值介绍 asp.net MVC漏油配置总结

    为什么说JAVA中要慎重使用继承   这篇文章的主题并非鼓励不使用继承,而是仅从使用继承带来的问题出发,讨论继承机制不太好的地方,从而在使用时慎重选择,避开可能遇到的坑. JAVA中使用到继承就会有两 ...

  3. ECMAScript---布尔类型、null、undefined详解

    布尔类型中 至只有 true和false 在开发中它是非常重要的两个值,尤其是在条件判断中 如何把其他类型转换为布尔类型? 1.Boolean() Boolean(1); //true Boolean ...

  4. Shell脚本 /dev/null 2>&1详解

    Shell脚本---- /dev/null 2>&1详解   1.可以将/dev/null看作"黑洞". 它非常等价于一个只写文件. 所有写入它的内容都会永远丢失. ...

  5. 详解nohup /dev/null 2>&1 含义的使用

    https://www.jb51.net/article/169837.htm 这篇文章主要介绍了详解nohup /dev/null 2>&1 含义的使用,文中通过示例代码介绍的非常详细 ...

  6. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  7. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  8. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  9. Android中Activity运行时屏幕方向与显示方式详解

    现在我们的手机一般都内置有方向感应器,手机屏幕会根据所处位置自动进行横竖屏切换(前提是未锁定屏幕方向).但有时我们的应用程序仅限在横屏或者竖屏状态下才可以运行,此时我们需要锁定该程序Activity运 ...

随机推荐

  1. Python的包管理工具Pip

    接触了Ruby,发现它有个包管理工具RubyGem非常好用,而且有非常完备的文档系统http://rdoc.info 发现Python下也有相同的工具,包含easy_install和Pip.只是,我没 ...

  2. LINUX 内核2

    http://blog.csdn.net/acs713/article/category/1363650

  3. Hive中数据的加载和导出

    原文:http://blog.javachen.com/2014/06/09/hive-data-manipulation-language.html 关于 Hive DML 语法,你可以参考 apa ...

  4. Linux内核加载全流程

    无论是Linux还是Windows,在加电后的第一步都是先运行BIOS(Basic Input/Output System)程序——不知道是不是所以的电脑系统都是如此.BIOS保存在主板上的一个non ...

  5. SQL Insert语句数据以以unicode码存储 解决存储数据出现乱码的问题

    写了个读取原始的文本数据导入数据库的工具 ,最后发现空中有几个值是乱码 例如 原始数据是 :Bjørn 存到数据库中是 Bj?rn 研究半天发现是一直以来忽略了一个标记‘N’ 2条 Insert 语句 ...

  6. C#当前应用程序路径及环境变量

    一.获取当前文件的路径 1. System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName 获取模块的完整路径.可获得当前执行的 ...

  7. Flask与Ajax

    这篇短文使用jquery. Flask提供一个很简单的方法来处理Ajax请求——在视图函数中用request的属性is_xhr来判断,如果是true则是异步请求. Jquery的$.getJSON() ...

  8. pycharm中文乱码的问题

    这几天一直挺困扰的是使用pycharm之后一直对中文的乱码,即使添加了很多别人说的类似于#coding:utf-8的语句但是还是报错,让我抓狂,但是今天终于找到了解决的办法,还真的是让人很高兴啊,哈哈 ...

  9. Laravel_Elixir_gulp任务利器安装

    目录 说明 安装 1安装gulp 2安装Elixir 3Elixir快速入门 4合并cssjs 5版本控制version 6复制copy 7方法串联 1.说明 详细说明暂时省略,后期补充.小白的角度理 ...

  10. 关于css制作圆角

    三个阶段: 1.背景图片: 2.css2.0+标签模拟圆角: 3.css3.0圆角属性(border-radius). 1.1.背景图片--宽度固定,高度自适应圆角 为容器设置宽度 在主体的上方加一个 ...