null相关
本文轉(zhuǎn)自:http://www.cnblogs.com/peida/archive/2013/06/14/Guava_Optional.html?
null代表不確定的對象:
Java中,null是一個關(guān)鍵字,用來標(biāo)識一個不確定的對象。因此可以將null賦給引用類型變量,但不可以將null賦給基本類型變量。
Java中,變量的使用都遵循一個原則:先定義,并且初始化后,才可以使用。例如如下代碼中,我們不能定義int?age后,不給age指定值,就去打印age的值。這條對對于引用類型變量也是適用的(String name也同樣適用),在編譯的時候就會提示為初始化。
public class NullTest {public static void testNull(){int age;System.out.println("user age:"+age);long money;money=10L;System.out.println("user money"+money);String name;System.out.println("user name:"+name);} }在Java中,Java默認(rèn)給變量賦值:在定義變量的時候,如果定義后沒有給變量賦值,則Java在運行時會自動給變量賦值。賦值原則是整數(shù)類型int、byte、short、long的自動賦值為0,帶小數(shù)點的float、double自動賦值為0.0,boolean的自動賦值為false,其他各供引用類型變量自動賦值為null。上面代碼會變?yōu)槿缦驴蛇\行代碼:
public class NullTest {public static void testNull(){int age = 0;System.out.println("user Age:"+age);long money;money=10L;System.out.println("user money"+money);String name = null;System.out.println("user name:"+name);} }null本身不是對象,也不是Objcet的實例:
null只是一個關(guān)鍵字,用來標(biāo)識一個不確定的對象,他既不是對象,也不是Objcet對象的實例。下面我們通過代碼確定一下null是不是Object對象實例:
public class NullTest {public static void main(String[] args) {testNullObject();}public static void testNullObject() {if (null instanceof java.lang.Object) {System.out.println("null屬于java.lang.Object類型");} else {System.out.println("null不屬于java.lang.Object類型");}} }運行上面代碼,輸出:null不屬于java.lang.Object類型,可見,null對象不是Object對象的實例。
? null對象的使用:
1.常見使用場景:
有時候,我們定義一個引用類型變量,在剛開始的時候,無法給出一個確定的值,但是不指定值,程序可能會在try語句塊中初始化值。這時候,我們下面使用變量的時候就會報錯。這時候,可以先給變量指定一個null值,問題就解決了。例如:??
Connection conn = null;try {conn = DriverManager.getConnection("url", "user", "password");} catch (SQLException e) {e.printStackTrace();}String catalog = conn.getCatalog();如果剛開始的時候不指定conn = null,則最后一句就會報錯。
2.容器類型與null:
???? List:允許重復(fù)元素,可以加入任意多個null。
???? Set:不允許重復(fù)元素,最多可以加入一個null。
???? Map:Map的key最多可以加入一個null,value字段沒有限制。
???? 數(shù)組:基本類型數(shù)組,定義后,如果不給定初始值,則java運行時會自動給定值。引用類型數(shù)組,不給定初始值,則所有的元素值為null。
?
?????3.null的其他作用
???? 1>、判斷一個引用類型數(shù)據(jù)是否null。 用==來判斷。
???? 2>、釋放內(nèi)存,讓一個非null的引用類型變量指向null。這樣這個對象就不再被任何對象應(yīng)用了。等待JVM垃圾回收機制去回收。
4.null的使用建議:
1>. 在Set或者Map中使用null作為鍵值指向的value,千萬別這么用。很顯然,在Set和Map的查詢操作中,將null作為特殊的例子可以使查詢結(jié)果更淺顯易懂。
2>. 在Map中包含value是null值的鍵值對,你應(yīng)該把這種鍵值對移出map,使用一個獨立的Set來包含所有null或者非null的鍵。很容易混淆的是,一個Map是不是包含value是 null的key,還是說這個Map中沒有這樣的鍵值對。最好的辦法就是把這類key值分立開來,并且好好想想到底一個value是null的鍵值對對于你的程序來說到底意味著什么。
3>. 在列表中使用null,并且這個列表的數(shù)據(jù)是稀疏的,或許你最好應(yīng)該使用一個Map<Integer,E>字典來代替這個列表。因為字典更高效,并且也許更加精確的符合你潛意識里對程序的需求。
4>. 想象一下如果有一種自然的“空對象”可以使用,比方說對于枚舉類型,添加一個枚舉常數(shù)實例,這個實例用來表示你想用null值所表示的情形。比如:Java.math.RoundingMode有一個常數(shù)實例UNNECESSARY來表示“不需要四舍五入”,任何精度計算的方法若傳以RoundingMode.UNNECESSARY為參數(shù)來計算,必然拋出一個異常來表示不需要舍取精度。
5.問題和困惑:
首先,對于null的隨意使用會一系列難以預(yù)料的問題。通過對大量代碼的研究和分析,我們發(fā)現(xiàn)大概95%以上的集合類默認(rèn)并不接受null值,如果有null值將被放入集合中,代碼會立刻中斷并報錯而不是默認(rèn)存儲null值,對于開發(fā)來說,這樣能夠更加容易的定位程序出錯的地方。
另外,null值是一種令人不滿的模糊含義。有的時候會產(chǎn)生二義性,這時候我們就很難搞清楚具體的意思,如果程序返回一個null值,其代表的含義到底是什么,例如:Map.get(key)若返回value值為null,其代表的含義可能是該鍵指向的value值是null,亦或者該鍵在map中并不存在。null值可以表示失敗,可以表示成功,幾乎可以表示任何情況。用其它一些值(而不是null值)可以讓你的代碼表述的含義更清晰。
反過來說,使用null值在有些情況下是一種正確的選擇,因為從內(nèi)存消耗和效率方面考慮,使用null更加廉價,而且在對象數(shù)組中出現(xiàn)null也是不可避免的。但是在程序代碼中,比方說在函數(shù)庫中,null值的使用會變成導(dǎo)致誤解的元兇,也會導(dǎo)致一些莫名的,模糊的,很難修正的問題。就像上述map的例子,字典返回null可以代表的是該鍵指向的值存在且為空,或者也可以代表字典中沒有這個鍵。關(guān)鍵在于,null值不能指明到底null代表了什么含義。
Guava的Optional:
大多數(shù)情況下程序員使用null是為了表示某種不存在的意思,也許應(yīng)該有一個value,但是這個value是空或者這個value找不到。比方說,在用不存在的key值從map中取 value,Map.get返回null表示沒有該map中不包含這個key。
若T類型數(shù)據(jù)可以為null,Optional<T>是用來以非空值替代T數(shù)據(jù)類型的一種方法。一個Optional對象可以包含一個非空的T引用(這種情況下我們稱之為“存在的”)或者不包含任何東西(這種情況下我們稱之為“空缺的”)。但Optional從來不會包含對null值的引用。
import com.google.common.base.Optional;public class OptionalTest {public void testOptional() throws Exception { Optional<Integer> possible=Optional.of(6);if(possible.isPresent()){System.out.println("possible isPresent:"+possible.isPresent());System.out.println("possible value:"+possible.get());}} }?
由于這些原因,Guava庫設(shè)計了Optional來解決null的問題。許多Guava的工具被設(shè)計成如果有null值存在即刻報錯而不是只要上下文接受處理null值就默認(rèn)使用null值繼續(xù)運行。而且,Guava提供了Optional等一些工具讓你在不得不使用null值的時候,可以更加簡便的使用null并幫助你避免直接使用null。
Optional<T>的最常用價值在于,例如,假設(shè)一個方法返回某一個數(shù)據(jù)類型,調(diào)用這個方法的代碼來根據(jù)這個方法的返回值來做下一步的動作,若該方法可以返回一個null值表示成功,或者表示失敗,在這里看來都是意義含糊的,所以使用Optional<T>作為返回值,則后續(xù)代碼可以通過isPresent()來判斷是否返回了期望的值(原本期望返回null或者返回不為null,其意義不清晰),并且可以使用get()來獲得實際的返回值。
Optional方法說明和使用實例:
1.常用靜態(tài)方法:
Optional.of(T):獲得一個Optional對象,其內(nèi)部包含了一個非null的T數(shù)據(jù)類型實例,若T=null,則立刻報錯。
Optional.absent():獲得一個Optional對象,其內(nèi)部包含了空值
Optional.fromNullable(T):將一個T的實例轉(zhuǎn)換為Optional對象,T的實例可以不為空,也可以為空[Optional.fromNullable(null),和Optional.absent()等價。
使用實例如下:
import com.google.common.base.Optional;public class OptionalTest {@Testpublic void testOptional() throws Exception { Optional<Integer> possible=Optional.of(6);Optional<Integer> absentOpt=Optional.absent();Optional<Integer> NullableOpt=Optional.fromNullable(null);Optional<Integer> NoNullableOpt=Optional.fromNullable(10);if(possible.isPresent()){System.out.println("possible isPresent:"+possible.isPresent());System.out.println("possible value:"+possible.get());}if(absentOpt.isPresent()){System.out.println("absentOpt isPresent:"+absentOpt.isPresent()); ;}if(NullableOpt.isPresent()){System.out.println("fromNullableOpt isPresent:"+NullableOpt.isPresent()); ;}if(NoNullableOpt.isPresent()){System.out.println("NoNullableOpt isPresent:"+NoNullableOpt.isPresent()); ;}} }2.實例方法:
1>. boolean isPresent():如果Optional包含的T實例不為null,則返回true;若T實例為null,返回false
2>. T get():返回Optional包含的T實例,該T實例必須不為空;否則,對包含null的Optional實例調(diào)用get()會拋出一個IllegalStateException異常
3>. T or(T):若Optional實例中包含了傳入的T的相同實例,返回Optional包含的該T實例,否則返回輸入的T實例作為默認(rèn)值
4>. T orNull():返回Optional實例中包含的非空T實例,如果Optional中包含的是空值,返回null,逆操作是fromNullable()
5>. Set<T> asSet():返回一個不可修改的Set,該Set中包含Optional實例中包含的所有非空存在的T實例,且在該Set中,每個T實例都是單態(tài),如果Optional中沒有非空存在的T實例,返回的將是一個空的不可修改的Set。
使用實例如下:
輸出結(jié)果:
獲得返回值: -12 獲得返回值 orNull: null 獲得返回值 set 的 size : 1 獲得返回值: 15 獲得返回值 orNull: 15 Optional除了給null值命名所帶來的代碼可閱讀性的提高,最大的好處莫過于Optional是傻瓜式的。Optional對象的使用強迫你去積極的思考這樣一種情況,如果你想讓你的程序返回null值,這null值代表的含義是什么,因為你想要取得返回值,必然從Optional對象內(nèi)部去獲得,所以你必然會這么去思考。但是只是簡單的使用一個Null值會很輕易的讓人忘記去思索代碼所要表達(dá)的含義到底是什么,盡管FindBugs有些幫助,但是我們還是認(rèn)為它并沒有盡可能的解決好幫助程序員去思索null值代表的含義這個問題。
這種思考會在你返回某些存在的值或者不存在的值的時候顯得特別相關(guān)。和其他人一樣,你絕對很可能會忘記別人寫的方法method(a,b)可能會返回一個null值,就好像當(dāng)你去寫method(a,b)的實現(xiàn)時,你也很可能忘記輸入?yún)?shù)a也可以是null。如果返回的是Optional對象,對于調(diào)用者來說,就可以忘卻怎么去度量null代表的是什么含義,因為他們始終要從optional對象中去獲得真正的返回值。
轉(zhuǎn)載于:https://www.cnblogs.com/YDDMAX/p/4973305.html
總結(jié)
- 上一篇: IT 企业稿阿米巴 失败
- 下一篇: jQuery EasyUI使用教程之创建