1. 程式人生 > >關於Java Primitive型別與內建Wrapper型別使用過程中的一點小總結

關於Java Primitive型別與內建Wrapper型別使用過程中的一點小總結

最近在寫程式碼時由於對於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值問題,還是在實際程式碼中總結吧,這裡不多說。