Java中有关null的9件事

作者:网络    软件教程库   2020-05-16

java中有关 null 的9件事

对于java程序员来说,null是令人头痛的东西。时常会受到空指针异常(npe)的骚扰。

连java的发明者都承认这是他的一项巨大失误。java为什么要保留null呢?null出现有一段时间了,并且我认为java发明者知道null与它解决的问题相比带来了更多的麻烦,但是null仍然陪伴着java。

我越发感到惊奇,因为java的设计原理是为了简化事情,那就是为什么没有浪费时间在指针、操作符重载、多继承实现的原因,null却与此正好相反。好吧,我真的不知道这个问题的答案,我知道的是不管null被java开发者和开源社区如何批评,我们必须与null共同存在。与其为null的存在感到后悔,我们倒不如更好的学习null,确保正确使用null。

为什么在java中需要学习null?因为如果你对null不注意,java将使你遭受空指针异常的痛苦,并且你也会得到一个沉痛的教训。精力充沛的编程是一门艺术,你的团队、客户和用户将会更加欣赏你。以我的经验来看,导致空指针异常的一个最主要的原因是对java中null的知识还不够。你们当中的很多已经对null很熟悉了,但是对那些不是很熟悉的来说,可以学到一些关于null老的和新的知识。让我们一起重新学习java中null的一些重要知识吧。


java中的 null 是什么 ?

正如我说过的那样,null是java中一个很重要的概念。null设计初衷是为了表示一些缺失的东西,例如缺失的用户、资源或其他东西。但是,一年后,令人头疼的空指针异常给java程序员带来不少的骚扰。在这份材料中,我们将学习到java中null关键字的基本细节,并且探索一些技术来尽可能的减少null的检查以及如何避免恶心的空指针异常。

1)首先,null是java中的关键字,像public、static、final。它是大小写敏感的,你不能将null写成null或null,编译器将不能识别它们然后报错。

object obj = null; // not ok
object obj1 = null //ok

使用其他语言的程序员可能会有这个问题,但是现在ide的使用已经使得这个问题变得微不足道。现在,当你敲代码的时候,ide像eclipse、netbeans可以纠正这个错误。但是使用其他工具像notepad、vim、emacs,这个问题却会浪费你宝贵时间的。


2)就像每种原始类型都有默认#20540;一样,如int默认#20540;为0,boolean的默认#20540;为false,null是任何引用类型的默认#20540;,不严#26684;的说是所有object类型的默认#20540;。就像你创建了一个布尔类型的变量,它将false作为自己的默认#20540;,java中的任何引用变量都将null作为默认#20540;。这对所有变量都是适用的,如成员变量、局部变量、实例变量、静态变量(但当你使用一个没有初始化的局部变量,编译器会警告你)。为了证明这个事实,你可以通过创建一个变量然后打印它的#20540;来观察这个引用变量,如下图代码所示:

privatestatic object myobj;
publicstatic void main(string args[]){
    system.out.println(what is value of myobjc :  + myobj);
}
what is value of myobjc : null

这对静态和非静态的object来说都是正确的。就像你在这里看到的这样,我将myobj定义为静态引用,所以我可以在主方法里直接使用它。注意主方法是静态方法,不可使用非静态变量。

3)我们要澄清一些误解,null既不是对象也不是一种类型,它仅是一种特殊的#20540;,你可以将其赋予任何引用类型,你也可以将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#39;s possible, no error

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


4)null可以赋#20540;给引用变量,你不能将null赋给基本类型变量,例如int、double、float、boolean。如果你那样做了,编译器将会报错,如下所示:

inti = null;// type mismatch : cannot convert from null to int
shorts = null;//  type mismatch : cannot convert from null to short
byteb = null:// type mismatch : cannot convert from null to byte
doubled = null;//type mismatch : cannot convert from null to double
 
integer itr = null;// this is ok
intj = itr; // this is also ok, but nullpointerexception at runtime

正如你看到的那样,当你直接将null赋#20540;给基本类型,会出现编译错误。但是如果将null赋#20540;给包装类object,然后将object赋给各自的基本类型,编译器不会报,但是你将会在运行时期遇到空指针异常。这是java中的自动拆箱导致的,我们将在下一个要点看到它。


5) 任何含有null#20540;的包装类在java拆箱生成基本数据类型时候都会抛出一个空指针异常。一些程序员犯这样的错误,他们认为自动装箱会将null转换成各自基本类型的默认#20540;,例如对于int转换成0,布尔类型转换成false,但是那是不正确的,如下面所示:

integer iamnull = null;
inti = iamnull; // remember - no compilation error

但是当你运行上面的代码片段的时候,你会在控制台上看到主线程抛出空指针异常。在使用hashmap和integer键#20540;的时候会发生很多这样的错误。当你运行下面代码的时候就会出现错误。


importjava.util.hashmap;
importjava.util.map;
 
/**
 * an example of autoboxing and nullpointerexcpetion
 *
 * @author windows 8
 */
publicclass test {
    publicstatic void main(string args[]) throwsinterruptedexception {
      map numberandcount = newhashmap();
      int[] numbers = {3,5,7,9,11,13,17,19,2,3,5,33,12,5};
 
      for(inti : numbers){
         intcount = numberandcount.get(i);
         numberandcount.put(i, count++); // nullpointerexception here
      }      
    }
}


输出:

exceptioninthread mainjava.lang.nullpointerexception
 at test.main(test.java:25)

这段代码看起来非常简单并且没有错误。你所做的一切是找到一个数字在数组中出现了多少次,这是java数组中典型的寻找重复的技术。开发者首先得到以前的数#20540;,然后再加一,最后把#20540;放回map里。程序员可能会以为,调用put方法时,自动装箱会自己处理好将int装箱成interger,但是他忘记了当一个数字没有计数#20540;的时候,hashmap的get()方法将会返回null,而不是0,因为integer的默认#20540;是null而不是0。当把null#20540;传递给一个int型变量的时候自动装箱将会返回空指针异常。设想一下,如果这段代码在一个if嵌套里,没有在qa环境下运行,但是你一旦放在生产环境里,boom:-)


6)如果使用了带有null#20540;的引用类型变量,instanceof操作将会返回false:

integer iamnull = null;
if(iamnullinstanceofinteger){
   system.out.println(iamnull is instance of integer);                            
 
}else{
   system.out.println(iamnull is not an instance of integer);
}

输出:

i

amnull is not an instance of integer

这是instanceof操作一个很重要的特性,使得对类型强制转换检查很有用


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

publicclass testing {             
   publicstatic void main(string args[]){
      testing myobject = null;
      myobject.iamstaticmethod();
      myobject.iamnonstaticmethod();                            
   }
 
   privatestatic void iamstaticmethod(){
        system.out.println(i am static method, can be called by null reference);
   }
 
   privatevoid iamnonstaticmethod(){
       system.out.println(i am non static method, don#39;t date to call me by null);
   }

输出:

i am static method, can be called by null reference
exceptioninthread mainjava.lang.nullpointerexception
               at testing.main(testing.java:11)

8)你可以将null传递给方法使用,这时方法可以接收任何引用类型,例如public void print(object obj)可以这样调用print(null)。从编译角度来看这是可以的,但结果完全取决于方法。null安全的方法,如在这个例子中的print方法,不会抛出空指针异常,只是优雅的退出。如果业务逻辑允许的话,推荐使用null安全的方法。

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

publicclass test {
 
    publicstatic void main(string args[]) throwsinterruptedexception {
 
       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 truein java

这是关于java中null的全部。通过java编程的一些经验和使用简单的技巧来避免空指针异常,你可以使你的代码变得null安全。因为null经常作为空或者未初始化的#20540;,它是困惑的源头。对于方法而言,记录下null作为参数时方法有什么样的行为也是非常重要的。总而言之,记住,null是任何一个引用类型变量的默认#20540;,在java中你不能使用null引用来调用任何的instance方法或者instance变量。


java中有关 null 的9件事

原文地址:http://blog.csdn.net/gao_chun/article/details/45429759

软件教程库 该篇文章地址:https://www.itjcku.com/9999/1091445.html

阅读全部内容


Tags:中有

返回首页



推荐内容

LDAP账号同步和Windows域集成验证

#65279;#65279; paradise.ezla.com.tw/files/article/html/32/32 ...

在同一个sql语句中如何写不同条件的count数量(转)

select sum(case when (t.条件字段=‘00‘) then 1 else 0 ...

详解MessageBox(),MsgBox函数的正确使用

//或者使用chr(13),chr(10)效果一样 msgbox aamp;chr(13)amp;bamp;chr( ...

swift学习笔记5

五、集合 数组 1、泛型 arraylt;类型gt; 2、简化[类型] var myar:arraylt;stringg ...

约在CBD,吃饭

午饭当然是外卖。 cbd上班的同仁们不用约,都去了一间叫大食堂的餐厅。 它在商业街繁华地段的二楼,有1000平米。你不知 ...

headFirst学习笔记之十:状态模式(5.2)

1.如何从状态图得到真正的代码: (1)找出所有状态:没有25分钱,有25分钱,糖果售罄,售出糖果。 (2)创建一个实例 ...

zabbixPHPdatabasessupportoffFail

zabbix初始化检查安装环境不通过: php databases support off fail --未找到所 ...

JS中字符串,数组常见操作

字符串mdash;mdash;mdash;》数组 abc =gt; ["a","b","c"]直接使用split方法 ...

IOS简单的动画自定义方法(旋转、移动、闪烁等)

#define kdegreestoradian(x) (m_pi * (x) /180.0) #define kra ...

swift学习笔记3-4

再牛逼的梦想,也抵不住你傻逼似的坚持! 我跑啊跑啊,为的就是赶上那个被寄予厚望的自己。 三、运算符+表达式 swift允 ...

Trie树初学

#includelt;cstdiogt; #includelt;cstringgt; #includelt;cstdli ...

Android--状态栏高度

干货 classlt;gt; c = null; object obj = null; field field = n ...

//hdu2222//AC自动机初学

// hdu2222 // #includelt;cstdiogt; #includelt;cstringgt; #in ...

黑书笔记

就从p77开始记好了.(稍微扩容) p77 排序. 1.香农信息论 基于比较的排序不可能突破o(nlogn)的复杂度限制 ...

//codeforces471D//kmp初学

// codeforces 471d // #includelt;cstdiogt; #includelt;cstrin ...

搭建基于域名虚拟主机

修改主配置文件 # cd /etc/httpd/conf.d/ # vim vhost.conf lt;virtu ...

Mysql5.6.24zip解压缩版配置及修改默认编码方法

win64位下载地址: http://dev.mysql.com/downloads/file.phpid=456319 ...

图片的预加载和按需加载

图片预加载 lt;!doctype htmlgt; lt;htmlgt; lt;headgt; lt;meta htt ...

iPhone/iPad程序怎么禁止自动休眠

//禁止自动休眠可以通过这一句话搞定:[uiapplication sharedapplication].idletim ...

普林斯顿《算法II》第一周学习笔记UndirectedGraph

普林斯顿的算法课是cousera上评价挺高的一门课,课程的教学语言用的是java,课程中的算法都会被封装成类的形式,对于 ...

headFirst学习笔记之九:迭代器与组合模式(5.1)

1.任务: 大新闻!对象村餐厅和对象村煎饼屋合并了!可以在同一个地方吃早饭和午饭了hohoho(有什么好开森的对象村的小 ...

IOSapplicationWillResignActive

一、挂起当有电话进来或者锁屏,这时你的应用程会挂起,在这时,uiapplicationdelegate委托会收到通知,调 ...

哥我要向前看了

七年前的五一节前的那个周六,我遇到生命中一个重要的人。虽然相处短暂,好梦不长,但是回忆丰满,念念不忘。 七年后的五一节, ...

GoldSmith第二章

uhf:特高频 300m-3000mhz shf:超高频 3g-30g 所有发射与接收的信号都是实信号(因为调制器的振荡 ...

动态规划总结【模板】

最长递增子序列 给定一个序列,找到最长子序列的长度,使得子序列中的所有元素被排序的顺序增加。 1.求最长递增子序列的 ...

HDUACM1103Flo'sRestaurant

分析:借助stl的min_element实现。每次更新最先被占用的桌子,具体见注释。 #includelt;iostre ...

【翻译自mos文章】Oracledb12c中,每次日志切换时,会改变alert_sid.log的权限

12c中,每次日志切换时,会改变alert_sid.log的权限 来源于: alert log file‘s perm ...

poj1988(并查集)

题意:有30000个木块,编号从1到30000,然后有两种操作m a b,把木块a所在的堆块放到木块b所在的堆块上,操作 ...

org.hibernate.exception.GenericJDBCException:Couldnotopenconnection

1、错误描述 org.hibernate.exception.genericjdbcexception: could ...

ubuntu下mysql导出数据

使用的是workbench,原因时workbench的导出工具mysqldump和mysql的版本不一致,这个时候手动指 ...


本网站部分内容来自互联网,版权归原作者所有,文章内容仅代表原作者个人观点。如有侵权请联系我们删除 电子邮件 itjcku@foxmail.com