第一次在博客里写学习心得笔记,如果有错的地方请指正。

    以前学习过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