java中的:++、--、==、equals

本篇主要来说说java中的这几个经常令人头疼的运算符和函数:–,++,== ,equals

1、先来看++与–
代码注释中已经写的很清楚了,这里就不在解释

public static void test1(){
        //++i是先i自加1,然后在使用i的值
        //i++是先用i的值,在i自加1
        int i =1;
        System.out.println(++i);  //  2    ++i,是先i自加1,然后在使用i的值,1+1=2,用i的值就是输出时用了,于是2
        System.out.println(i++);  //  2    i++,是先用i的值,用,这里体现为输出,先输出2,输出过后i再自加1
        System.out.println(i);    //  3
        System.out.println(--i);  //  2    同上
        System.out.println(i--);  //  2
        System.out.println(i);    //  1

        // 可以大概的理解为后缀+与后缀-是整行代码都运行过之后再在自行加或减,在整行代码运行时,取的都是未进行后加或后减之前的值
    }

2、再来看看 == 与equals
首先要说明 == 在判断的时候分为两种情况,基本类型和引用类型
2.1、 == 在比较两个基本类型的时候,比较的是他们的值
2.2、 而 == 在比较两个引用类型的时候,比较的是引用所指向的对象的地址值。所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。
看一段代码

        Integer i1= new Integer(1);
        Integer i2= new Integer(1);
        System.out.println(i1==i2);   // false
        System.out.println(i1.equals(i2));  //  true 

        String s1=new String("a");
        String s2=new String("a");
        System.out.println(s1==s2);        // false
        System.out.println(s1.equals(s2)); // true

以上代码中,Integer 为引用类型,于是i1==i2,比较的是对象的地址值,new了两个Integer对象,每new一个对象,就会在堆中给该对象分配一个地址,这两个对象的地址值当然是不同的,所以是false。String 为引用类型,于是s1==s2,比较的也是对象的地址值,当然还是false。

下面咱们再来看看equals:
java中的所有类都继承自Object这个类,那么,equals方法也是从object类中继承过来的,Object中的equals函数的源码,使用的也是==

public boolean equals(Object var1) {
        return this == var1;
}

那么问题就来了,既然都是继承的Object,那么equals也是从Object继承来的,使用的是==,==在比较引用类型的时候比价的是地址值,那么下面的带码中比较的也是地址值,因该是false才对,为什么是true呢?

 System.out.println(i1.equals(i2));  //  true 
 System.out.println(s1.equals(s2)); // true

答案就是,String和Integer类中的equals被重写了,他们不再是用== 来比较了
string类中的equalse源码:又判断是否是同一个对象,又是各种转换,总之一句话,equals已经被重写了,被重写后比较的是对象中的内容是否相同,于是对象中的内容都是a,当然返回的是true了。小伙伴们有兴趣了,也可以自己定义个类,然后在类中重写equals方法。

public boolean equals(Object var1) {
        if (this == var1) {  // 如果传进来的var1与this(本对象)是同一个对象那么肯定相同:调用代码的时候是a.equals(b)这里的this值的就是a
            return true;
        } else {
            if (var1 instanceof String) {
                String var2 = (String)var1;
                int var3 = this.value.length;
                if (var3 == var2.value.length) {
                    char[] var4 = this.value;
                    char[] var5 = var2.value;

                    for(int var6 = 0; var3-- != 0; ++var6) {
                        if (var4[var6] != var5[var6]) {
                            return false;
                        }
                    }
                    return true;
                }
            }
            return false;
        }
    }

Integer类中的equals源代码:
这代码倒是干脆的很,直接从对象中取值来比较了,所以Integer中的equals重写后也是比较的对象的内容,于是i1.equals(i2)当然是true了,因为他们对应的对象中的值都是1

 public boolean equals(Object var1) {
        if (var1 instanceof Integer) {
            return this.value == (Integer)var1;
        } else {
            return false;
        }
    }

下面再来看一个例子

        String s3="abc";
        String s4="abc";
        System.out.println(s3==s4);   // true
        System.out.println(s3.equals(s4)); // true

== 比较引用类型是,比较的是对象的地址值,为啥第1个是true呢?
这就涉及到了内存中的常量池,常量池属于方法区的一部分,当运行到s3创建对象时,如果常量池中没有,就在常量池中创建一个对象”abc”,第二次创建的时候,就直接使用,所以两次创建的对象其实是同一个对象,它们的地址值相等。

String str1 = new String("abc");

这里其实创建了两次对象,依次是在常量池中创建了对象”abc”,一次是在堆内存中创建了对象str1,所以str1和str2的地址值不相等。
然后比较的时候比较的是堆内存中的地址值,所以不相等。

猜你喜欢

转载自blog.csdn.net/java_xxxx/article/details/81234921