编程习惯——非空判断

从刚开始学编程就经常会看到许多地方有类似 if(XX==null)之类的语句,总觉得有点不解,直到现在开始参与项目才懂得非空判断的意义与重要性,觉得自己对null和其他空值的理解太过模糊,于是系统的学习了一下,写个总结,希望可以对有同样需求的人有一定参考作用。

  • 1.空值有哪些类型
  • 2.为什么要做空判断
  • 3.用return减少嵌套

1、空值有哪些类型

一般来说空值是指null,但是只判断null并不能解决所有问题,除了常见的空字符串,长度为0数组,还有其他一些基本数据类型的默认值等。所以这里说的空值并不仅限严格意义上的空值,包括了其他可能代表无数据、没有值或者需要判断的情况。

1.1基本数据类型

对于八种基本类型来说去判断==null是错误的,因为基本类型的取值范围并没有null,即使声明后没有进行赋值Java也会根据不同类型给予初始值,整数类型int、byte、short、long的默认值为0,带小数点的float、double默认值为0.0,boolean的默认值为false,char的默认值是‘’
所以判断的参数是八种基本类型时应该注意不能判断==null,应该根据类型选择对比的值,虽然直接使用这些默认值不像null会引起空指针异常,但是作为数据是否被有效赋值的判断在很多情况下也是必要的。

1.2 引用数据类型

当我们声明一个非基本数据类型变量,而不进行赋值的情况下,java会自动赋值null。所以当我们去调用这个未赋值变量的方法,或者访问其内部变量的时候就会抛出空指针异常,也是最常见需要if(xxx==null)语句的情况。比较值得注意的是有一些具有内部对象的模型类,要考虑到内部对象是否为null的情况。

1.2.1、 String

String虽然也是继承自Object,默认值也为null,但是对于常见的应用场景,空串""也是我们应该进行判断的情况。可以用:
if(s == null || s.length() <= 0){......} //s是一个String类型
进行判断,
需要注意s == null是必要且必须在前面的,否则会因为null调用方法而抛出空指针异常。

1.3 容器类

1.3.1、 数组

基本上有4种情况:

  • 1 声明但不定义长度,值为null
  • 2 长度为0数组,不为null,但注意不可直接取出元素,会抛出索引越界错误(ArrayIndexOutOfBoundsException)
  • 3 基本类型数组声明且定义长度,但不赋值,所有元素值为该基本类型默认值
  • 4 引用类型数组声明且定义长度,但不赋值,所有元素为null
    int[] arrayNull;  //值为null
    int[] arrayZero = new int[0]; //值为{}
    int[] arrayInt = new int[2];  //值为{0,0}
    Object[] arrayObj = new Object[2];  //值为{null,null}
1.3.2、 集合
  • 不赋值的情况下为null
  • List:允许重复元素,可以加入任意多个null。
  • Set:不允许重复元素,最多可以加入一个null。
  • Map:Map的key最多可以加入一个null,value字段没有限制。

常见数据类型对应需要判断的空值

(其实我只是想试试用markdown画表而已.......)

类型 所属 空值、默认值或可能需要处理的值
int 基本数据类型 0
float、double 基本数据类型 0.0
String 引用数据类型 null、""
数组 容器类 null、{}、{null}、{0,0} 等等
List 容器类 null、内部元素为null

</br></br>

2、为什么要做空判断

往大了说就是让程序具有健壮性还有防御性编程之类的大东西了,但是作为新手对这些东西理解过于模糊,所以结合项目实际分析,列出以下几点:

2.1、避免空指针异常

在定义变量而不赋值的情况下,除了基本数据类型,其他类型变量都会默认为null。
null也可以认为是除基本数据类型外其他类型的默认值,所以一个含参数的方法,只要参数不为基本数据类型,在调用时都可以填入null为参数。

public void funcString(String s) {
    s.isEmpty();
  }

 //在main方法中调用
funcString(null);      //参数传入null  IDE并不会报错 可以进行编译

//运行后会抛出NullPointerException

可以看出null作为参数传入方法,但是一旦传入null,内部相当于进行了这一过程null.isEmpty();报错也就很正常了。
所以类似这种需要对对象的方法进行方法调用的情况加一个非空判断就非常必要了。
再举一个比较实际的例子:

假设服务器返回这样的一段json数据

{
        "id": 5,
        "title": "我是文章标题",
        "comment": {
            "userid": 4,
            "content": "我是评论内容~~~"
        }
    }

现在把它映射成这样的一个对象

public class Article {
  
  private int id; //文章id
  private String title;//文章标题
  private Comment comment;//文章评论

  class Comment {
    //内部对象“评论”
    private int userId;//评论用户Id
    private String content;//评论内容

    public int getUserId() {
      return userId;
    }

    public void setUserId(int userId) {
      this.userId = userId;
    }

    public String getContent() {
      return content;
    }

    public void setContent(String content) {
      this.content = content;
    }
  }

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getTitle() {
    return title;
  }

  public void setTitle(String title) {
    this.title = title;
  }

  public Comment getComment() {
    return comment;
  }

  public void setComment(Comment comment) {
    this.comment = comment;
  }
}

以安卓最基本的控件TextView为例,我们现在把文章评论的内容显示出来

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textView = (TextView) findViewById(R.id.txt);
    String commentContent=getArticle().getComment().getContent();
    textView.setText(commentContent);
  }

public Article getArticle(){
    //获取数据 映射成Article对象 并返回
  }

以上的例子并没有加入非空判断,而文章评论也顺利的显示出来了
但是,如果一篇刚发布的文章,看到的人可能都没几个,又怎么会有评论呢?服务器返回的数据很可能是这样的:

{
        "id": 6,
        "title": "我是文章标题",
        "comment": {   
        }
    }

这时这段代码

 String commentContent=getArticle().getComment().getContent();

运行时就变成了

String commentContent=null.getContent();

所以必须加入非空判断:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textView = (TextView) findViewById(R.id.txt);
    if (getArticle().getComment()!=null){
    String commentContent=getArticle().getComment().getContent();
    textView.setText(commentContent);
    }
  }

2.2、增加程序性能

同样以上面的例子来说,这段代码

 String commentContent=getArticle().getComment().getContent();

也可以通过try catch语句来捕捉空指针异常并进行处理
但是通过非空判断的方式,当程序运行到if (getArticle().getComment()!=null),就不再继续进行,从性能的角度说也更合适。

</br></br>

3、用return减少嵌套

使用非空判断的时候因为要使用到if--else语句,不免要多出一些嵌套,当逻辑比较简单的时候还好,如果复杂一点的逻辑就可能要使用到多重嵌套,看着一堆迷之缩进是很影响代码可读性的,所以从小养成用return语句减少嵌套的习惯是很重要的。

继续优化上面那段代码:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textView = (TextView) findViewById(R.id.txt);
    if (getArticle().getComment() == null) return; //把判断条件改为相反 一旦符合return结束方法
    String commentContent = getArticle().getComment().getContent();
    textView.setText(commentContent);
  }

使用return后少了一对花括号,在这个例子里可能看不出太大好处,但是在一些复杂判断多重嵌套下,使用return可以明显提升代码可读性。

另外需要用else的时候也可以这样:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textView = (TextView) findViewById(R.id.txt);
    if (getArticle().getComment() == null) {
      //把else里的语句 放到里面 最后加上return 跳过后面语句
      textView.setText("暂时没有评论");
      return;
    }
    String commentContent = getArticle().getComment().getContent();
    textView.setText(commentContent);
  }

</br></br>

总结

主要还是理清你写的方法接收的参数或者是Api接收的数据是什么类型,有哪些可能性。然后对症下药去写判断就行啦~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,296评论 18 399
  • 《ijs》速成开发手册3.0 官方用户交流:iApp开发交流(1) 239547050iApp开发交流(2) 10...
    叶染柒丶阅读 4,750评论 0 7
  • 新工作的前两天我一直重复复制黏贴的工作,以能够在短时间内找到完成更多的文章。 虽然这样简单的一个工作,可是也感觉有...
    北小舟阅读 333评论 0 1
  • 清风拂面布谷啼,麦浪翻滚众鸟飞。 拨开云雾日出现,扫尽一夜心头绪。 人生八九不如意,莫问前程何处去。 能以所喜为生...
    君小白阅读 159评论 0 4