個人學習心得筆記之java中"=="

    第一次在博客裏寫學習心得筆記,如果有錯的地方請指正。

    以前學習過C語言,“==”就是“==”左右項的數值的比較,這個習慣讓我在Java學習中困惑了。經過查找資料發現“==”不單單是等號左右兩項數值的比較,還可以是引用對象的比較;那到底什麼時候是引用對象的比較什麼時候是數值的比較呢(暫時不管String類型)?

總結:1:基本數據類型(byte,short,int,long,float,double,char,boolean)直接定義的都是數值比較,如:int i=2;byte j=2;double k=2.0;等等;

      2:類(Byte, Short, Integer, Long, Character, Boolean)實現的,都是引用對象比較,如:Integer i=2;Byte j=2;Long k=2;等等;

      3:如果爲數值比較的,直接比較其數值即可,如果是類實現的引用對象就要考慮常量池了。如果“==”左右兩項一邊是基本數據類型一邊是類實現的方法,看成數值比較即可;

    

    下面對引用對象中使用到的常量池談談感想:

    感悟較深的示例如下:(注:以下代碼必須使用JDK1.5版本以上纔可以實現)
示例1:

Integer i=127;Integer j=127;System.out.println(i==j);//結果是true。


示例2:

Integer i=128;Integer j=128;System.out.println(i==j);//結果是false。


    兩個示例除了數值不一樣外其它代碼都一樣,但是結果卻不一樣,明顯問題就出在這個數值上了。
    通過查找資料發現兩個都是引用對象比較,結果不同,主要原因是一個數值在常量池的範圍內一個不在這個範圍內。

    常量池我也是這幾天才知道東西。
    對於常量池,深的我還不瞭解,但是現在我記住了這3句話(外加自己理解的,不知道是否正確),
    (1)Java的8種基本類型對應的類(Byte, Short, Integer, Long, Character, Boolean, Float, Double), 除Float和Double以外, 其它六種都實現了常量池, 但是它們只在大於等於-128並且小於等於127時才使用常量池。

     (如果問爲什麼數值是在這個區間呢?在Jdk幫助文檔中對public static Integer valueOf(int i)的解釋如下:返回一個表示指定的 int 值的 Integer 實例。如果不需要新的 Integer 實例,則通常應優先使用該方法,而不是構造方法 Integer(int),因爲該方法有可能通過緩存經常請求的值而顯著提高空間和時間性能。

代碼如下:

    public static Integer valueOf(int i) 
    {    
        final int offset = 128;    //定義一個不可變的int類型常量
        if (i >= -128 && i <= 127) //當數值在-128到127之間時,不是在創建新的對象而是直接去常量池中查找
        {      
            return IntegerCache.cache[i + offset];//爲什麼是i+offset,主要是因爲數組的下標是從0開始的(個人認爲) 
        }    
            return new Integer(i);    
     }

)
    (2)常量池中的相同數值所對應的引用對象都是同一個地址,數值不同的肯定是不同的地址了(即常量池中不會出現相同數值出現不同地址,因爲常量池是爲了節省內存空間和時間而實現的優化方法)。
    (3)創建上面六種已經實現常量池的類型對象時(不是new出來的),都會先到常量池中查找是否有相同的數值,有相同數值則引用,沒有則創建並加到常量池中。


    上面的六種已經實現常量池的類,這些類可以通過new實現實例化,但是通過new實現的實例化對象的數據都不存放到常量池中,而是存放到中,而且每new一個對象都新申請一個堆空間存放數據。示例如下:

示例3:

Integer i=new Integer(127);Integer j=new Integer(127);System.out.println(i==j);//結果爲false

示例4:

Integer i=new Integer(128);Integer j=new Integer(128);System.out.println(i==j);//結果爲false

    因爲每個new出來的對象所指向的地址都是不一樣的,所以結果都是false

     對於上面的比較的做了一個總結的示例,代碼如下:

public class Test
{
    public static void main(String[] args)
    {
        int int1=1;
        int int2=1;
        System.out.println("int1與int2都爲1時:"+(int1==int2));
        
        int1=-129;
        int2=-129;
        System.out.println("int1與int2都爲-129時:"+(int1==int2));
        
        int1=128;
        int2=128;
        System.out.println("int1與int2都爲128時:"+(int1==int2));
        
        Integer integer1=1;
        Integer integer2=1;
        System.out.println("integer1與integer2都爲1時:"+(integer1==integer2));
        
        integer1=-129;
        integer2=-129;
        System.out.println("integer1與integer2都爲-129時:"+(integer1==integer2));
        
        integer1=128;
        integer2=128;
        System.out.println("integer1與integer2都爲128時:"+(integer1==integer2));
        
        Integer newInteger9=new Integer(1);
        Integer newInteger10=new Integer(1);
        System.out.println("newInteger9與newInteger10都爲1時:"+(newInteger9==newInteger10));
        
        Integer newInteger5=new Integer(-129);
        Integer newInteger6=new Integer(-129);
        System.out.println("newInteger5與newInteger6都爲-129時:"+(newInteger5==newInteger6));
        
        Integer newInteger7=new Integer(128);
        Integer newInteger8=new Integer(128);
        System.out.println("newInteger7與newInteger8都爲128時:"+(newInteger7==newInteger8));
        
        //重新賦值同樣是引用常量池中的數值
        newInteger5=1;
        newInteger6=1;
        System.out.println("newInteger5與newInteger6都重新賦值爲1時:"+(newInteger5==newInteger6));
        
        //賦值的數值超出了常量池的範圍,所以不是引用常量池中的數值而是重新創建一個空間
        newInteger5=128;
        newInteger6=128;
        System.out.println("newInteger5與newInteger6都重新賦值爲128時:"+(newInteger5==newInteger6));
        
        int1=1;//基本數據類型
        integer1=1;//類實現的方法
        newInteger5=1;//使用了new實現的方法
        //此時int1和integer1值都爲1,但是內存中的地址是不一樣的
        System.out.println("int1與integer1都重新賦值爲1時:"+(int1==integer1));
        //此時int1和newInteger5的值都爲1,但是內存中的地址是不一樣的
        System.out.println("int1與newInteger5都重新賦值爲1時:"+(int1==newInteger5));
        //此時integer1與newInteger5的值都爲1,且都是引用了常量池的數值
        System.out.println("integer1與newInteger5都重新賦值爲1時:"+(integer1==newInteger5));
    }
}

執行結果爲:

int1與int2都爲1時:true
int1與int2都爲-129時:true
int1與int2都爲128時:true
integer1與integer2都爲1時:true
integer1與integer2都爲-129時:false
integer1與integer2都爲128時:false
newInteger9與newInteger10都爲1時:false
newInteger5與newInteger6都爲-129時:false
newInteger7與newInteger8都爲128時:false
newInteger5與newInteger6都重新賦值爲1時:true
newInteger5與newInteger6都重新賦值爲128時:false
int1與integer1都重新賦值爲1時:true
int1與newInteger5都重新賦值爲1時:true
integer1與newInteger5都重新賦值爲1時:true


對於“==”的比較,左右項還可以是String類型的比較,由於認知有限,暫時只能理解這個解釋,通俗易懂,地址:http://developer.51cto.com/art/201106/266454.htm







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章