封面
:學校內的秋天
背景:寫這個的原因,也是我這兩天湊巧看到的,雖然我一直有
alibaba Java
開發手冊,也看過不少次,但是一直沒有注意過這個問題?屬於那種看過,但又沒完全看過?
一起來看看吧衝咯?
hxdm,我寫不出小故事?,但是可不可以看在我寫了不少,還算實用的份上,給個贊?啊。
在這裡請xdm 喝 ?啦
一、前言?
今天在寫一個AdvertVO
類時,我當時用 id 是直接給了個 long
,沒有使用用包裝型別,然後 idea 裡面的 Alibaba Java Coding Guidelines
外掛就直接給了個黃色波浪線,ALT+ENTER
一看,阿里巴巴Java開發手冊 的提示說:
關於基本資料型別與包裝資料型別的使用標準如下:
1) 所有的POJO類屬性必須使用包裝資料型別。
2) RPC方法的返回值和引數必須使用包裝資料型別。
3) 所有的區域性變數推薦使用基本資料型別。說明:POJO類屬性沒有初值是提醒使用者在需要使用時,必須自己顯式地進行賦值,任何NPE問題,或者入庫檢查,都由使用者來保證。
我剛看的時候,稍稍有點點沒完全理解這個意思(可能是我比較菜,沒有經歷過這樣的場景),然後為了搞懂自己心裡的小疑惑?,就?
接下來我們弄一個簡單的例子來理解理解,之後再聊聊實際發生的場景,以及會產生的危害
二、例子?
public class Main {
private static Integer a1;
private static int a2;
private static Boolean b1;
private static boolean b2;
public static void main(String[] args) {
System.out.println("Integer ==> a1:"+a1);
System.out.println("int ==> a2:"+a2);
System.out.println("Boolean ==> b1:"+b1);
System.out.println("boolean ==> b2:"+b2);
}
/**
* 結果:
* Integer ==> a1:null
* int ==> a2:0
* Boolean ==> b1:null
* boolean ==> b2:false
*/
}
所有的包裝型別在我們沒有賦值的時候,都是直接預設 null 值的,而基本型別都會初始化一個預設值。
也就是說,包裝型別的預設值都是null,而基本資料型別的預設值是一個固定值,如boolean是false,byte、short、int、long是0,float是0.0f等;
??可能 xdm 平時有注意到,但又沒有完全注意到,用 基本型別和包裝型別之間的區別。下面我們用場景說一說區別:??
三、場景?
【正例】:資料庫的查詢結果可能是 null,因為自動拆箱,用基本資料型別接收有 NPE 風險。( NPE 下文有解釋)
【反例】:某業務的交易報表上顯示成交總額漲跌情況,即正負 x%,x 為基本資料型別,呼叫的 RPC 服務,呼叫不成功時,返回的是預設值,頁面顯示為 0%,這是不合理的,應該顯示成中劃線-。所以包裝資料型別 的 null 值,能夠表示額外的資訊,如:遠端呼叫失敗,異常退出。
1)場景一⛵
我們再舉一個扣費的例子,我們做一個扣費系統,扣費時需要從外部的定價系統中讀取一個費率的值,我們預期該介面的返回值中會包含一個浮點型的費率欄位。當我們取到這個值得時候就使用公式:金額*費率=費用 進行計算,計算結果進行劃扣。
如果由於計費系統異常,他可能會返回個預設值,如果這個欄位是 Double 型別的話,該預設值為 null ,如果該欄位是 double 型別的話,該預設值為 0.0。
如果扣費系統對於該費率返回值沒做特殊處理的話,拿到null值進行計算會直接報錯,阻斷程式。拿到 0.0可能就直接進行計算,得出介面為 0 後進行扣費了。這種異常情況就無法被感知。
有人說,那我可以對 0.0 做特殊判斷,如果是 0 一樣可以阻斷報錯啊。但是,這時候就會產生一個問題,如果允許費率是 0 的場景又怎麼處理呢?(如下例)
一個小小結論:使用基本型別可能會在一定程度上增大系統的複雜性,讓坑變得越來越多。還有這種使用包裝型別定義變數的方式,通過異常來阻斷程式的執行,進而可以被立馬識別到這種綫上問題。但是我們如果使用基本資料型別的話,系統可能認為無異常,從而繼續執行。只能被動的測試出現問題,更甚的是如果是線上出現這種問題,我想可能...都明白哈。
2)場景二?
簡單來說就是我們如果自定義了一個 Student 類,其中有一個屬性是成績 score .
如果用 Integer 而不用 int 定義,一次考試,學生可能沒考,值是null,也可能考了,但考了0分,值是0.
public class Student {
private Integer score;
private int score;
}
請注意
:這兩個表達的狀態明顯不一樣 。如果我們用包裝型別的話,null的話證明沒有考,0的話證明考了0分;但是如果我們用基本型別的話,這兩種情況都是一個樣的,沒法區分的。
四、NPE 問題?
【推薦】防止 NPE,是程式設計師的基本修養,注意 NPE 產生的場景:
NPE,指為基本型別的資料返回null值,防止NPE是程式設計師的基本休養。所有NPE的場景:
返回型別為基本資料型別,return包裝資料型別的物件時,自動拆箱有可能產生NPE。
public int f() { return Integer 物件; } 如果為null,自動解箱拋NPE。
- 資料庫的查詢結果可能為 null。
- 集合裡的元素即使 isNotEmpty,取出的資料元素也可能為 null。
- 遠端呼叫返回物件時,一律要求進行空指標判斷,防止 NPE。
- 對於 Session 中獲取的資料,建議進行 NPE 檢查,避免空指標。
- 級聯呼叫 obj.getA().getB().getC() ;一連串呼叫,易產生 NPE。
正例:使用 JDK8 的 Optional 類來防止 NPE 問題。瞭解?JDK8 Optional 類
五、自言自語?
你好,我是博主
寧在春
:segmentfault主頁希望本篇文章能讓你感到有所收穫!!!
祝
我們:待別日相見時,都已有所成
。歡迎大家一起討論問題?,躺了?
參考:Alibaba Java 開發手冊