Java 之NullPointerException

  • 為什么我們應(yīng)該避免NullPointerException

在Android開發(fā)中,最常見的就是NullPointerException,然而這個異常最致命便是導致了APP閃退,如果你在開發(fā)過程中沒有過多的關(guān)注對象是否為null而輕易的調(diào)用其中的方法,那APP的閃退則很大程度是因為你沒有檢查null情況。然而在繁忙的開發(fā)過程中,導致我們每次使用引動都必須測試是否為Null,在代碼上枯燥且冗余。問題在于null 除了在你試圖用它執(zhí)行任何操作來產(chǎn)生NullPointerException之外,它自己沒有任何行為,這讓我們很沮喪。

  1. 何為空對象概念

空對象最有用之處在于它更靠近數(shù)據(jù),因為對象表示的是問題空間的實體。在接下來的例子中,都有一個Student類,而在代碼里面,有很多情況目前你都沒有一個實際的Student,通常你會使用null引用并且測試它。與此不同的是,我們?nèi)匀皇褂每諏ο?。但是這個空對象可以響應(yīng)“實際”對象響應(yīng)的所有消息,但是你仍然需要以某種方式測試它是否為空。最簡單的方式是創(chuàng)建一個標記借口:

public interface Null()

首先我們先來一個最常見的學生類
public class Student implements Null{ private String name; private String age; private String major; public Student(String name, String age, String major) { this.name = name; this.age = age; this.major = major; } @Override public String toString() { return "Student{" + "name='" + name + '\'' +", age='" + age + '\'' +", major='" + major + '\'' +'}'; } public static class NULLStudent extends Student implements Null{ private NULLStudent(){ super("","","");} @Override public String toString() { return "Nullperson"; } } public static final Student NULL = new NULLStudent(); }

  • 我們?nèi)绾蝿?chuàng)建空對象類以及如何處理空對象

通常,空對象都是單例,因此這里作為靜態(tài)final實例創(chuàng)建。這可以正常工作,如果你想要修改一個NullStudent,那只能用一個新的對象來替換它。此處你可以用instanceof來探測是Null 還是更具體的NullStudent,但是此處我們使用了單例方式,所有你甚至可以用equals和==來和Student.Null來比較。

接下來我們來編寫一個Position類,其中涉及到當我們沒有Student對象時如何來處理。
public class Position { private String titile; private Student student; public Position(String titile, Student student) { this.titile = titile; this.student = student; if(this.student == null){ this.student = Student.NULL; } } public Position(String titile) { this.titile = titile; this.student = Student.NULL; } public String getTitile() { return titile; } public void setTitile(String titile) { this.titile = titile; } public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; if(this.student == null){ this.student = Student.NULL; } } @Override public String toString() { return "Position{" +"titile='" + titile + '\'' +", student=" + student +'}'; } }
有了Positon類,此時你就不需要創(chuàng)建空對象了,因為Student.Null的存在就表示一個空的Position。
現(xiàn)在我們編寫一個Staff來實現(xiàn)填充職位時查詢空對象。
public class Staff extends ArrayList<Position>{ public void add(String titile,Student student) { add(titile,student); } public void add(String... titles) { for (String title: titles) { add(new Position(title)); } } public Staff(String... titles) { add(titles); } public boolean positionAvailable(String title) { for (Position position : this) { if(position.getTitile().equals(title) && position.getStudent() == Student.NULL) { return true; } } return false; } public void fillPosition(String title,Student hire) { for (Position position : this) { if(position.getTitile() == title && position.getStudent() == Student.NULL) { position.setStudent(hire); return; } } throw new RuntimeException("Position" + title + "not available"); } public static void main(String[] agrs){ Staff staff = new Staff("CTO","Marketing Manager","SoftWare Engineer","Test Engineer","Technical writer"); staff.fillPosition("CTO",new Student("ME","24","CS")); staff.fillPosition("SoftWare Engineer",new Student("Another","21","unKonw")); if(staff.positionAvailable("Technical writer")) { staff.fillPosition("Technical writer",new Student("Finch","18","City")); } System.out.println(staff); } }

  • 最后關(guān)于空對象我想說的

注意 你在某些地方仍然必須測試他是否為空對象,但你永遠不會引用到null,取而代之的則是我們編寫的NULL對象(空的數(shù)據(jù)實體)。在某種程度上我們能確保你不會因為無意間引用到null而導致NullPointerException。進而導致令人頭大的APP 閃退的問題。
最后我想說的是, 關(guān)于空和無的區(qū)別。 空在某種程度上是占據(jù)空間的實體,然而無則不是。對應(yīng)這篇文章想說的則是,如果在之前我們常用的null 則可以對應(yīng)無。然而我們編寫的NULL類則可以對應(yīng)空,它可以作為一個數(shù)據(jù)實體存在,只是它作為一個數(shù)據(jù)實體暫時里面數(shù)據(jù)為空而已。如果可以我們應(yīng)該盡量避免只是使用null,這是C語言留下的習慣,但是我們在JAVA完全可以避免這些。

  • PS 關(guān)于Collection里面的空對象

在我們編寫我們對象實體數(shù)據(jù)類的時候,我們可以采取這種方式來規(guī)避Null,其實在容器類中,Collections工具類以及提供靜態(tài)方法返回相關(guān)的空容器返回,所以下次從網(wǎng)絡(luò)獲取數(shù)據(jù)為空的時候完全可以返回一個不可以改變的空容器。用法如下:

  Collections.EMPTY_LIST
       空的列表(不可變的)。
  Collections.EMPTY_MAP
       空的映射(不可變的)。
  Collections.EMPTY_SET
       空的 set(不可變的)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,728評論 18 399
  • 5繼承 5.1 類、超類和子類 重用部分代碼,并保留所有域?!癷s-a”關(guān)系,用extends表示。 已存在的類被...
    我快要上天啦閱讀 953評論 1 3
  • 一. Java基礎(chǔ)部分.................................................
    wy_sure閱讀 4,012評論 0 11
  • 民間有句老話“百練走為先”。長期徒步對于整個的心、肺功能都有很大的鍛煉作用,而且走路的時候需要消耗熱量,那么對于消...
    最熱話題精選閱讀 17,238評論 0 51
  • 2017.8.28星期一 結(jié)婚很多年了日子過得像流水一樣平淡而從容,習慣了在油鹽醬醋茶中磨練冷靜,也逐漸從一個愛做...
    擷一朵鏡中花閱讀 142評論 0 0

友情鏈接更多精彩內(nèi)容