常言道:“細節決定成敗”,程式設計更是如此。
近期,我參加的一個項目,讓我對此體會深刻。
這個專案屬於推薦系統的一部分,我負責的一塊是進行MapRedcue編程,計算影片之間的相似度!另一位同事就把我計算出來的結果用Sqoop匯入到資料庫中,供線上呼叫。
在導入資料的過程中,總是爆出java.lang.NumberFormatException異常,我認為是他那裡的原因,他的Sqoop沒有進行空行或空格過濾,我的相似度結果是沒有錯的。後來他把一部分相似度結果複製到Notepad裡面,發現有的資料有空格,他是直接讀入,然後進行轉換,當然就出現問題了。我不知道Sqoop能不能進行空格過濾,但是,我的程式可以控制輸出的結果,所以就對每一個輸出結果都呼叫了java.lang.String類別的trim()方法。最終問題解決。
空格,總是會造成一些小問題,但不容忽視。消除空格,記得呼叫trim()方法。
另一個問題是基本資料型別的封裝類別進行比較的時候,可能不是比較的數值,而是記憶體的位址!
相似度計算的過程中,有一個地方需要進行java.lang.Long類型之間的相等判斷。我發現最終的相似度輸出結果不正確時,排查原因,最終定位到這裡。原來的程式碼是這樣的:
if(lg1 == lg2){ return true; }
lg1和lg2都是java.lang.Long類型,我在這裡是想判斷lg1和lg2的數值是否相等,之前,我只是籠統地記得,Java的封裝類別進行比較的時候會進行轉換的,所以就這樣寫了!但是這樣寫也可能比較大不是數值,而是他們各自在記憶體中的位址。
我用Google搜尋了這個問題,網路上說,java.lang.Float類型和java.lang.Double類型使用「==」進行相等判斷需要轉換成基本資料類型,java.lang.Integer和java.lang.Long則不需要轉換,Java會自動轉換的。但是,我自己做的測試跟這種說法有出入。以下是測試程式碼:
package org.jindao.basic; /** * @author * @date 2013年10月25日 上午7:30:47 */ public class BasicTest { public static void main(String[] args) { Integer ig1 = 3; Integer ig2 = 3; System.out.println("Integer ig1 = 3,Integer ig2 = 3 ig1==ig2的结果为:"+(ig1==ig2)); Integer ig3 = new Integer(3); Integer ig4 = new Integer(3); System.out.println("Integer ig3 = new Integer(3),Long ig4 = new Integer(3) ig3==ig4的结果为:"+(ig3==ig4)); Long lg1 = 3l; Long lg2 = 3l; System.out.println("Long lg1 = 3l,Long lg2 = 3l lg1==lg2的结果为:"+(lg1==lg2)); Long lg3 = new Long(3); Long lg4 = new Long(3); System.out.println("Long lg3 = new Long(3),Long lg4 = new Long(3) lg3==lg4的结果为:"+(lg3==lg4)); Float flt1 = 3.2f; Float flt2 = 3.2f; System.out.println("Float flt1 = 3.2f,Float flt2 = 3.2f flt1==flt2的结果为:"+(flt1==flt2)); Float flt3 = new Float(3.2); Float flt4 = new Float(3.2); System.out.println("Float flt3 = new Float(3.2),Float flt4 = new Float(3.2)) flt3==flt4的结果为:"+(flt3==flt4)); Double db1 = 3.2; Double db2 = 3.2; System.out.println("Double db1 = 3.2,Double db2 = 3.2 db1==db2的结果为:"+(db1==db2)); Double db3 = new Double(3.2); Double db4 = new Double(3.2); System.out.println("Double db3 = new Double(3.2),Double db4 = new Double(3.2) db3==db4的结果为:"+(db3==db4)); } }
執行結果:
Integer ig1 = 3,Integer ig2 = 3 ig1==ig2的结果为:true Integer ig3 = new Integer(3),Long ig4 = new Integer(3) ig3==ig4的结果为:false Long lg1 = 3l,Long lg2 = 3l lg1==lg2的结果为:true Long lg3 = new Long(3),Long lg4 = new Long(3) lg3==lg4的结果为:false Float flt1 = 3.2f,Float flt2 = 3.2f flt1==flt2的结果为:false Float flt3 = new Float(3.2),Float flt4 = new Float(3.2)) flt3==flt4的结果为:false Double db1 = 3.2,Double db2 = 3.2 db1==db2的结果为:false Double db3 = new Double(3.2),Double db4 = new Double(3.2) db3==db4的结果为:false
從結果可以看出,只有Integer和Long型別直接賦數值的時候,使用「==」判斷相等才會為true,其餘的時候都為false。
也就是說其餘的情況比較多都是變數在記憶體存放的位址,並不是變數的數值。
那為什麼Integer和Long型別直接賦數值,結果為true,而Float和Double型別直接賦數值,結果為false呢?我猜測,Java本身有最佳化措施,就是給Integer和Long型別直接賦數值的時候,記憶體裡面並沒有建立Integer和Long類型的對象,而是直接優化為基本資料型態int和long,所以是用「= =」判斷相等,結果才會為true。
為了保險起見,當判斷封裝類別變數的數值相等時,最好直接取出數值來進行「==」判斷,或是使用equals方法,即
lg1.equals(lg2)
像這些小細節,如果不搞清楚,說不定什麼時候就會造成*煩。
細節決定成敗,Java程式設計還有很多需要注意的細節,這裡只探討一二。
以上是Java程式設計中那些需要注意的細節的詳細內容。更多資訊請關注PHP中文網其他相關文章!