java nullpointerexception解決 - 什麼是NullPointerException,以及如何解決它?




6 Answers

當你聲明一個引用變量(即一個對象)時,你真的創建了一個指向對象的指針。 在聲明基本類型int的變量時考慮以下代碼:

int x;
x = 10;

在這個例子中,變量x是一個int ,Java會將它初始化為0。 當你在第二行中將它賦值為10時,你的值10被寫入x所指向的內存位置。

但是,當您嘗試聲明引用類型時會發生不同的事情。 採取以下代碼:

Integer num;
num = new Integer(10);

第一行聲明一個名為num的變量,但它不包含原始值。 相反,它包含一個指針(因為類型是Integer ,它是一個引用類型)。 既然你還沒有說Java到底指向什麼,它意味著“ 我沒有指向任何東西 ”。

在第二行中, new關鍵字用於實例化(或創建)Integer類型的對象,並且指針變量num被分配給該對象。 現在可以使用解引用操作符來引用該對象. (一個點)。

當您聲明一個變量但未創建對象時,您詢問的Exception就會發生。 如果您嘗試在創建對象之前解除引用num ,則會得到NullPointerException 。 在最微不足道的情況下,編譯器會捕獲這個問題,並讓你知道“num可能沒有被初始化”,但有時你會編寫不直接創建對象的代碼。

例如,你可能有一個方法如下:

public void doSomething(SomeObject obj) {
   //do something to obj
}

在這種情況下,您不是創建對象obj ,而是假設它是在doSomething方法被調用之前創建的。 不幸的是,可以像這樣調用方法:

doSomething(null);

在這種情況下, obj為空。 如果該方法旨在對傳入的對象執行某些操作,則拋出NullPointerException是合適的,因為這是程序員錯誤,程序員將需要該信息用於調試目的。

或者,可能會出現這樣的情況:方法的目的不僅僅是對傳入的對象進行操作,因此可能接受空參數。 在這種情況下,您需要檢查一個空參數並且行為不同。 你也應該在文檔中解釋這一點。 例如, doSomething可以寫成:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj != null) {
       //do something
    } else {
       //do something else
    }
}

最後, 如何使用堆棧跟踪查明異常位置和原因

nullpointerexception原因 numberformatexception意思

什麼是空指針異常( java.lang.NullPointerException )以及導致它們的原因?

可以使用哪些方法/工具來確定原因,以便阻止異常導致程序過早終止?




什麼是NullPointerException?

JavaDocs是一個很好的開始。 他們涵蓋了這些內容:

當應用程序嘗試在需要對象的情況下使用null時拋出。 這些包括:

  • 調用空對象的實例方法。
  • 訪問或修改空對象的字段。
  • 將null的長度視為數組。
  • 像訪問數組一樣訪問或修改null的槽。
  • 如果它是Throwable值,則拋出null。

應用程序應該拋出此類的實例來指示其他非法使用null對象。

同樣的情況是,如果您嘗試使用帶有synchronized的空引用,那麼也會根據JLS引發此異常:

SynchronizedStatement:
    synchronized ( Expression ) Block
  • 否則,如果Expression的值為null,則拋出NullPointerException

我如何解決它?

所以你有一個NullPointerException 。 你如何解決它? 我們來看一個拋出NullPointerException的簡單例子:

public class Printer {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print();
    }
}

識別空值

第一步是準確識別哪些值導致異常 。 為此,我們需要做一些調試。 學習閱讀堆棧跟踪很重要。 這會告訴你拋出異常的地方:

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

在這裡,我們看到第13行拋出異常(在printString方法中)。 查看該行並通過添加日誌語句或使用調試器來檢查哪些值為空。 我們發現s是空的,調用它的length方法會拋出異常。 當s.length()從方法中移除時,我們可以看到程序停止拋出異常。

跟踪這些值來自哪裡

接下來檢查這個值來自哪裡。 通過跟隨方法的調用者,我們看到sprint()方法中使用printString(name)傳入,並且this.name為null。

跟踪應該設置這些值的位置

this.name在哪裡設置? 在setName(String)方法中。 通過更多的調試,我們可以看到這個方法根本不被調用。 如果調用該方法,請確保檢查這些方法的調用順序 ,並且在打印方法之後不調用set方法。

這足以給我們一個解決方案:在調用printer.setName()之前添加對printer.setName()調用。

其他修補程序

該變量可以有一個默認值 (並且setName可以防止它被設置為null):

private String name = "";

print或者printString方法可以檢查null ,例如:

printString((name == null) ? "" : name);

或者你可以設計這個類,使得name 總是有一個非空值

public class Printer {
    private final String name;

    public Printer(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer("123");
        printer.print();
    }
}

也可以看看:

我仍然無法找到問題

如果您嘗試調試問題並且仍然沒有解決方案,可以發布一個問題以獲得更多幫助,但請確保包含迄今為止嘗試的內容。 至少在問題中包含堆棧跟踪 ,並在代碼中標記重要的行號 。 另外,請先嘗試簡化代碼(請參閱SSCCE )。




就像你試圖訪問一個null對像一樣。 考慮下面的例子。

TypeA objA;

這時你剛剛聲明了這個對象,但沒有初始化或實例化 。 每當你嘗試訪問其中的任何屬性或方法時,它將拋出NullPointerException ,這是有道理的。

請參閱下面的示例。

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown



NULL指針是指向無處的指針。 當你取消引用指針p ,你說“給我存儲在”p“中的位置的數據。當p是一個空指針時,存儲在p的位置是nowhere ,你說”給我在位置的數據'無處'“。顯然,它不能這樣做,所以它會拋出一個NULL pointer exception

一般來說,這是因為某些東西沒有被正確初始化。




空指針異常是指您正在使用對象而不進行初始化。

例如,下面是一個將在我們的代碼中使用它的學生類。

public class Student {

    private int id;

    public int getId() {
        return this.id;
    }

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

下面的代碼給你一個空指針異常。

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}

因為你正在使用Obj_Student ,但你忘記了像下面顯示的正確代碼那樣初始化它:

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student = new Student();
            obj_Student.setId(12);
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}



Java ,你聲明的所有變量實際上是對象(或基元)的“引用”,而不是對象本身。

當您嘗試執行一個對象方法時,引用會要求活動對象執行該方法。 但是如果引用是引用NULL(nothing,zero,void,nada),那麼方法就沒有辦法執行。 然後運行時通過拋出一個NullPointerException來讓你知道這一點。

你的引用是“指向”空,因此“空 - >指針”。

該對象位於VM內存空間中,訪問它的唯一方法是使用this引用。 以這個例子:

public class Some {
    private int id;
    public int getId(){
        return this.id;
    }
    public setId( int newId ) {
        this.id = newId;
    }
}
....
....
// Somewhere else...
Some reference = new Some();    // Point to a new object of type Some()
Some otherReference = null;     // Initiallly this points to NULL

reference.setId( 1 );           // Execute setId method, now private var id is 1

System.out.println( reference.getId() ); // Prints 1 to the console

otherReference = reference      // Now they both point to the only object.

reference = null;               // "reference" now point to null.

// But "otherReference" still point to the "real" object so this print 1 too...
System.out.println( otherReference.getId() );

// Guess what will happen
System.out.println( reference.getId() ); // :S Throws NullPointerException because "reference" is pointing to NULL remember...

這是一個重要的事情要知道 - 當沒有更多的對象引用(在上面的例子中,當referenceotherReference指向null),那麼對otherReference “不可達”的。 我們無法使用它,因此此對像被標記為垃圾收集,並且在某個時刻,VM將釋放此對象使用的內存並分配另一個內存。




Related

java nullpointerexception