關於Java Primitive型別與內建Wrapper型別使用過程中的一點小總結
阿新 • • 發佈:2019-02-15
最近在寫程式碼時由於對於Permitive型別和內建Wrapper型別使用不當,導致除錯程式除錯過程中出現了許多問題,在這裡簡單總結一下。
1.傳參
Permitive作形參時,若函式呼叫時使用Wrapper型別作實參,需要保證實參被初始化不為null。/** * Created by chuang on 15-8-12. */ public class PermitiveWrapperTest { public void testWrapperArg(Long param){ } public void testPermitiveArg(long param){ } public static void main(String[] argc){ PermitiveWrapperTest test = new PermitiveWrapperTest(); Long param = null; try { test.testWrapperArg(param); } catch (NullPointerException e){ System.out.println("testWrapperArg :"); e.printStackTrace(); } try { test.testPermitiveArg(param); } catch (NullPointerException e){ System.out.println("testPermitiveArg :"); e.printStackTrace(); } } }
上面這段程式碼的執行結果:
testPermitiveArg : java.lang.NullPointerException at com.xiaomi.browser.utils.PermitiveWrapperTest.main(PermitiveWrapperTest.java:29) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134) Process finished with exit code 0
可以看到,由於實參Long作為被初始化為null,導致呼叫函式形參為long型的函式時,出現空指標異常。 當把程式碼中的實參初始化改為
Long param = 1L;
或者
long param = 1;
則程式執行正常,不會有任何異常丟擲。
2.判等
程式碼如下:執行結果:long eqTestPrimitive = 1; Long eqTestWrapper = new Long(1); if(eqTestWrapper.equals(eqTestPrimitive)) { System.out.println("equals primitive variable true"); } if(eqTestWrapper.equals(1)) { System.out.println("equals primitive constant true"); } if(eqTestWrapper == eqTestPrimitive){ System.out.println(" == primitive variable true"); } if(eqTestWrapper == 1){ System.out.println(" == primitive const true"); }
testPrimitiveArg :
equals primitive variable true
== primitive variable true
== primitive const true
我們看到只有第二個判斷語句沒有返回true,即 if(eqTestWrapper.equals(1)) {
System.out.println("equals primitive constant true");
}
為什麼呢,我們看一下Long.equals的原始碼:
/**
* Compares this object to the specified object. The result is
* <code>true</code> if and only if the argument is not
* <code>null</code> and is a <code>Long</code> object that
* contains the same <code>long</code> value as this object.
*
* @param obj the object to compare with.
* @return <code>true</code> if the objects are the same;
* <code>false</code> otherwise.
*/
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
首先明確一點,Long.equals是為兩個Long型物件判等使用的,其內部還是用==判斷兩個物件內部所儲存的值是否相等。
返回我們最初遇到的問題,很容易就發現,之所以eqTestWrapper.equals(1)
返回false是因為,我們傳遞給equals函式的引數被作為Integer型別解析了,由此在equals函式內不第一個if型別判斷時就返回false了。將引數改為1L就返回true了,因為Java會內部裝箱,將引數升級為Long型。
Java中類似的問題還有好多,如Map的Key值問題,還是在實際程式碼中總結吧,這裡不多說。