2011-11-14 62 views
1

我想弄清楚提供不可用參數的方法調用如何在調用代碼行時拋出異常 - 在它到達方法行之前。 下面是一個例子java方法如何在調用之前拋出異常

1. static Integer x; 
2. public static void main(String args[]){ 
3. doStuff(x)} //null pointer exception thrown on this line 
//lines 4-49 
50. public static void doStuff(int z){} 

在這裏我發送整數對象參照方法,並且由於自動裝箱,整數對象爲有效參考進行發送。 如果被調用的方法在到達第50行之前沒有加載到堆棧上,那麼爲什麼JVM在第3行拋出空指針異常,但尚未得到方法簽名?

回答

1

If the invoked method is not loaded onto the stack until the line 50 is reached - 這是一個不正確的假設。

在自動裝箱並將Integer視爲int或反之亦然時,引擎會插入對intValue()或Integer.valueof()的調用。 - 這會導致空指針異常

Integer x = null; 
... 

doStuff(x.intValue()); 

所以intValue()上調用空:

它爲什麼如果你使用的類文件反編譯變得更加明顯。

2

null不能autounboxed爲有效int

可能有助於看看生成的實際字節碼。

public static void main(java.lang.String[]); 
    Code: 
    0: getstatic  #2; //Field i:Ljava/lang/Integer; 
    3: invokevirtual #3; //Method java/lang/Integer.intValue:()I <--- Your error comes from this line 
    6: invokestatic #4; //Method doStuff:(I)V 
    9: return 
6

因爲null不是用於原始int有效的值。

由於自動裝箱,Integer對象是接受基本原型int的方法的有效參數。但是,在這裏描述的情況下,Integer永遠不會被初始化,因此將爲nullInteger對象的默認未初始化值,與int爲0)不同。

這意味着JVM試圖通過調用null.intValue()使之適應正在被調用的方法投null到原始int - 那就是NPE被拋出在哪裏。

只是FYI,該方法聲明在調用它的行之下的事實沒有區別,因爲Java沒有被解釋,它被編譯成字節碼。

+0

雖然這是真的,並且是原因,但也許您可以多說明實際發生的情況? –

+3

生成的字節碼是doStuff(x.intValue()),所以如果x爲null,則有一個NPE – Molochdaa

1

因爲你的方法參數類型是「int」而不是「Integer」。所以JVM想要將Integer對象轉換爲「int」原始類型,並且您的對象爲null。所以這個轉換拋出異常。

0

假設我們有下面的代碼:

class Test { 
    public static Integer i; 

    public static void test(int x) {} 

    public static void main(String[] argv) { 
     test(i); 
    } 
} 

當我們反編譯程序,我們看到main編譯如下:

public static void main(java.lang.String[]); 
    Code: 
    0: getstatic #2; //Field i:Ljava/lang/Integer; 
    3: invokevirtual #3; //Method java/lang/Integer.intValue:()I 
    6: invokestatic #4; //Method test:(I)V 
    9: return 

因此,該方法被調用,即使前, JVM調用i.intValue(),這明顯產生了NullPointerException

相關問題