2012-02-29 40 views
1

我正在開始一個Java類,並無意中發現了什麼似乎是一個錯誤,而測試程序我寫的類。我不需要幫助做家庭作業。我想了解有關空值的兩件事情和解析空值的一件事。雙打NullExceptionHandling

首先,當你運行我的例子代碼,你會看到,點擊鞦韆上輸入框的「確定」按鈕沒有任何輸入存儲,似乎是一個空的字符串值。但是,當字符串被測試時,它不會測試爲空值。爲什麼是這樣?其次,當你運行我的示例代碼時,你會看到在swing輸入框中單擊'Cancel'按鈕存儲一個值,該值看起來像是一個包含文本「null」的字符串。這確實測試爲空值,但包含文本「null」的字符串顯然不會測試爲空。爲什麼當我認爲空字符串值爲「」時,取消按鈕生成一個帶有「null」文本的字符串?

最後,當您運行我的示例代碼時,您會看到被測試爲null的值在作爲double進行分析時會拋出NullPointerException,但是當它們被解析爲int時,它們不會引發NullPointerException。爲什麼是這樣?

我的老師不能回答這些問題。他認爲示例程序中的解析是算術實現的,因此整數可能會有不同的表現,因爲它們不處理小數點。這對我來說是有道理的,但如果是這種情況,爲什麼他們用像String這樣的空值解析不同?答案=「」;和由取消按鈕生成的空值?

我的示例代碼如下:

import javax.swing.*; 
    public class NullTest { 

public static void main(String[] args) { 
    //Demonstrate behavior with doubles. 
    throwingDoubles(); 

    //Demonstrate behavior with integers. 
    throwingInts();  
} 

public static void throwingDoubles() 
{ 

    //Loops three times so you can test each option. 
    for (int i = 0; i < 3; i++) 
    { 
     JOptionPane.showMessageDialog(null, "Double Tester\nFirst time through click ok without entering text.\nSecond time through click cancel.\nFinally type in null to prove that this string is not treated as a null value."); 
     String answer = JOptionPane.showInputDialog(null, "I would think 'answer' would be null if you click ok without entering anything."); 
     JOptionPane.showMessageDialog(null, "Double Tester\n'" + answer + "'\nIt appears null here if you don't enter anything, but as a string if you click cancel"); 

     if (answer==null) 
     { 
      JOptionPane.showMessageDialog(null, "Double Tester\nTested null"); 
      JOptionPane.showMessageDialog(null, "Double Tester\n'" + answer + "'\nIt appears the same here."); 
     } 
     else 
     { 
      JOptionPane.showMessageDialog(null, "Double Tester\nDid not test null"); 
      JOptionPane.showMessageDialog(null, "Double Tester\n'" + answer + "'\nIt appears the same here."); 
     } 

     try 
     { 
      double varDoub = Double.parseDouble(answer);  
     } 
     catch(NumberFormatException e) 
     { 
      JOptionPane.showMessageDialog(null, "Double Tester\nThis threw a NumberFormatException"); 
     } 
     catch(NullPointerException e) 
     { 
      JOptionPane.showMessageDialog(null, "Double Tester\nThis threw a NullPointerException"); 
     } 
     //An early escape clause. 
     if (JOptionPane.showConfirmDialog(null, "Run the loop again?")!=JOptionPane.OK_OPTION) 
     { 
      break; 
     } 
    } 
} 


public static void throwingInts() 
{ 

    //Loops three times so you can test each option. 
    for (int i = 0; i < 3; i++) 
    { 
     JOptionPane.showMessageDialog(null, "Int Tester\nFirst time through click ok without entering text.\nSecond time through click cancel.\nFinally type in null to prove that this string is not treated as a null value."); 
     String answer = JOptionPane.showInputDialog(null, "Int Tester\nI would think 'answer' would be null if you click ok without entering anything."); 
     JOptionPane.showMessageDialog(null, "Int Tester\n'" + answer + "'\nIt appears null here if you don't enter anything, but as a string if you click cancel"); 

     if (answer==null) 
     { 
      JOptionPane.showMessageDialog(null, "Int Tester\nTested null"); 
      JOptionPane.showMessageDialog(null, "Int Tester\n'" + answer + "'\nIt appears the same here."); 
     } 
     else 
     { 
      JOptionPane.showMessageDialog(null, "Int Tester\nDid not test null"); 
      JOptionPane.showMessageDialog(null, "Int Tester\n'" + answer + "'\nIt appears the same here."); 
     } 

     try 
     { 
      int varDoub = Integer.parseInt(answer); 
     } 
     catch(NumberFormatException e) 
     { 
      JOptionPane.showMessageDialog(null, "Int Tester\nThis threw a NumberFormatException"); 
     } 
     catch(NullPointerException e) 
     { 
      JOptionPane.showMessageDialog(null, "Int Tester\nWe never see this code. Why not?"); 
     } 
     //An early escape clause. 
     if (JOptionPane.showConfirmDialog(null, "Run the loop again?")!=JOptionPane.OK_OPTION) 
     { 
      break; 
     } 
    } 
} 

    } 

回答

3

首先,當你運行我的示例代碼,你會看到,點擊鞦韆上輸入框的「確定」按鈕沒有任何輸入存儲一個字符串值,似乎是空的。但是,當字符串被測試時,它不會測試爲空值。爲什麼是這樣?

因爲空字符串是不一樣的一個空值。如果在沒有文字的情況下點擊「確定」,則表示您接受空字符串作爲您提供的值。當您按下「取消」你實際上是說,「我拒絕提供價值」 - 這就是爲什麼返回值是記錄爲:

用戶的輸入,或者返回null意味着用戶取消了輸入

下一頁:

其次,當你運行我的示例代碼,你會看到,點擊「取消」按鈕,在鞦韆上輸入框存儲,似乎是包含文本「的字符串值空值」。這確實測試爲空值,但包含文本「null」的字符串顯然不會測試爲空。爲什麼當我認爲空字符串值爲「」時,取消按鈕生成一個帶有「null」文本的字符串?

不,它存儲的值是空引用。空引用是一樣要麼「」或「空的參考」。但是在字符串連接中,空引用被轉換爲「null」:"a" + null + "b"將最終爲"anullb"

瞭解引用如何在Java中工作是非常重要的。引用是一種導航到對象的方式,有效地......而空引用是一種說法,「沒有任何對象可以導航到」。如果您將參考值的變量想像爲寫有街道地址的紙張,如果值爲空,則紙張爲空白。

最後,當你運行我的示例代碼,你會看到,當作爲雙解析被作爲空測試值拋出NullPointerException,但是當他們被解析爲一個int他們不拋出NullPointerException。爲什麼是這樣?

看起來它只是在API中有點不一致。代替Integer.parseInt會拋出NumberFormatException。兩人的行爲如同記錄。

+0

'Double.parseDouble'正在調用'FloatingDecimal.readJavaFormatString',它使用String的'trim()'函數。這意味着如果你傳遞一個空字符串,你會得到一個NPE。 [Double](http://www.docjar.com/html/api/java/lang/Double.java.html),[FloatingDecimal](http://www.docjar.com/html/api/sun/misc /FloatingDecimal.java.html) – Deco 2012-02-29 07:53:50

+0

非常感謝。我認爲一個空字符串是一個空字符串,因此是一個空值。由於Java在很多方面與C#非常相似,這個概念會轉移到C#嗎? – Erik 2012-02-29 22:25:58

+0

@ErikBollinger:它的大部分功能確實如此 - 當然,空字符串引用與空字符串的引用沒有任何相同之處。一個空字符串是一個正常的字符串,它恰好沒有字符 - 你可以問它的長度等。 – 2012-02-29 22:30:49

0

我猜你的問題所在位置:

JOptionPane.showMessageDialog(null, "Double Tester\n'" + answer + "'\nIt appe... 
                 ^^^^^^ 

如果answernull(用戶按下Cancel),消息會出來爲:

雙計

它APPE ...

然而,當用戶按下Ok具有空輸入字段,answer引用一個空字符串""),由此得到:

雙儀

它APPE ...

問題是,您正在混淆null參考("null")的字符串值和空字符串("")。