equals和==的区别详解

1."=="

① 若==两边的是对象,则比较的是变量(存储于栈)存放的对象(存储于堆)的内存地址,判断两个引用是否指向堆中的同一块内存,是真正意义上的指针操作
② 如果是具体的阿拉伯数字的比较,值相等则为true,如:int a=10 与 long b=10L 与 double c=10.0都是相同的(为true),因为他们都指向地址为10的堆。
int a = 10;  
long b = 10L;  
double c = 10.0;  
System.out.println(a==c);//true  
System.out.println(b==c);//true 

2.equals()

equals方法位于object类中,由于所有的类都是继承自java.lang.Object类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,我们来看一下object中的方法:
public boolean equals(Object obj) {  
    return (this == obj);  
}
Object中的equals方法返回的是==的判断,所以在我们不重写object方法的的情况下,equals比较的结果与==比较的结果相同。在实际应用中,我们一般用equals来比较字符串的值,而String方法中给出了equals方法的重写:
public boolean equals(Object anObject) {  
    if (this == anObject) {  
        return true;  
    }  
    if (anObject instanceof String) {  
        String anotherString = (String)anObject;  
        int n = value.length;  
        if (n == anotherString.value.length) {  
            char v1[] = value;  
            char v2[] = anotherString.value;  
            int i = 0;  
            while (n-- != 0) {  
                if (v1[i] != v2[i])  
                    return false;  
                i++;  
            }  
            return true;  
        }  
     }  
     return false;  
}  
对equals的重写,保留了对地址是否相等的判断,若地址相同,那么两个引用指向的是堆中的同一块内存(引用指向同一个对象),那么毋庸置疑,两个值必然相等;如果两个地址不相等,判断其是否为字符串,是字符串的情况下,对值进行拆分,比较每个位置的字符是否相等(在不考虑其他因素的情况下,只对比字符,避免了地址对其影响)。

3.String的特殊性

① String s="abcd"是一种非常特殊的形式,和new 有本质的区别。它是java中唯一不需要new 就可以产生对象的途径。以String s="abcd";形式赋值在java中叫直接量,它是在常量池中而不是象new一样放在压缩堆中。这种形式的字符串,在JVM内部发生字符串拘留,即当声明这样的一个字符串后,JVM会在常量池中先查找有没有一个值为"abcd"的对象,如果有,就会把它赋给当前引用.即原来那个引用和现在这个引用指点向了同一对象,如果没有,则在常量池中新创建一个"abcd",下一次如果有String s1 = "abcd";又会将s1指向"abcd"这个对象,即以这形式声明的字符串,只要值相等,任何多个引用都指向同一对象.

② 而String s = new String("abcd");和其它任何对象一样.每调用一次就产生一个对象,只要它们调用。	
	
通俗讲:String str = "hello"; 先在内存中找是不是有"hello"这个对象,如果有,就让str指向那个"hello".如果内存里没有"hello",就创建一个新的对象保存"hello".;String str=new String ("hello") 就是不管内存里是不是已经有"hello"这个对象,都新建一个对象保存"hello"。
具体可以看下面的代码:
public static void main(String[] args) {  
        // a b 皆为引用  
    String a = new String("ab");  
    String b = new String("ab");  
          
    // aa bb存在于常量池中  
    String aa = "ab";  
    String bb = "ab";  
          
    // == 进行比较  
    System.out.println(aa == bb);// true  
    System.out.println(a == b);// false,非同一对象  
          
    // String类重写过的equals方法的比较  
    System.out.println(a.equals(b));// true  
    System.out.println(aa.equals(bb));// true  
}  

4.equals重写的注意事项

对equals重写需要注意五点:
  ① 自反性:对任意引用值X,x.equals(x)的返回值一定为true;
  ② 对称性:对于任何引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值一定为true;
  ③ 传递性:如果x.equals(y)=true, y.equals(z)=true,则x.equals(z)=true ;
  ④ 一致性:如果参与比较的对象没任何改变,则对象比较的结果也不应该有任何改变;
  ⑤ 非空性:任何非空的引用值X,x.equals(null)的返回值一定为false 。
  
equals:用于判断两个变量是否是对同一个对象的引用,即判断存放在堆中的内容是否相同.

  1. 对象不同,内容相同:

==:等于。比较两个地址是不是一样的(地址一样值肯定一样)(比较的是引用,引用是什么下面有介绍)

equals:相同。比较两个地址指向的 实际对象的内容 是不是同一个(比较的是对象)

两个长得一样的人,只能说长的相同(equals),但是不等于他们俩是一个人。

public class file2 {
 
    public static void main(String[] args) {
       //这句话设计到了两段不同内存,s是一段(存放在栈中),new String("java")(存放在堆中)是一段
        String s = new String("java");//s指向对象newString("java")的首地址。
        String s1 = new String("java");//s1指向对象new String("java")的首地址
 
        System.out.println(s==s1);            //false,两个不同的对象存放地址当然不一样
        System.out.println(s.equals(s1));    //true,地址中的值是一样的
  1. 同一对象,"等号和equals结果相同,引用类型做比较的时候两个都可以;

    引用类型:

    “引用”(reference)是c++的一种新的变量类型,是对C的一个重要补充。它的作用是为变量起一个别名。假如有一个变量a,想给它起一个别名,可以这样写:

    int a;int &b=a;

    这就表明了b是a的"引用",即a的别名。经过这样的声明,使用a或b的作用相同,都代表同一变量。在上述引用中,&是"引用声明符",并不代表地址。

    不要理解为"把a的值赋给b的地址"。引用类型的数据存储在内存的堆中,而内存单元中只存放堆中对象的地址。声明引用并不开辟新的内存单元,所以b和a都代表同一变量单元。

public class file2 {
 
    public static void main(String[] args) {
        String s1 = new String("java");
        String s2 = s1;
 
        System.out.println(s1==s2);            //true,s1,s2都指向了同一个地址
        System.out.println(s1.equals(s2));    //true  //true地址一样值当然一样
    }
 
}

3.这种情况值相同对象就是相同的

public class file2 {
 
    public static void main(String[] args) {
        String s1 = "java";
        String s2 = "java";//由于上一句已经把Java这个常量放入了常量池,所以这里对直接指向常量java的地址
 
        System.out.println(s1==s2);            //true,s1,s2存放的都是常量Java的首地址
        System.out.println(s1.equals(s2));    //true地址一样地址存放的值也是一样的
    }
 
}

最后补充一点,Java的基本变量和引用变量

基本变量:基本数据类型如char,byte,int,double,short,float,long,boolean,基本变量变量名是指向变量数据值。

引用变量:数组,对象,接口。变量名指向的是地址

所以才能有基本类型的变量用==就可以判断数值是否相等,毕竟是常量池中的同一个东西嘛

==比较对象时就是比较地址是否相等,String不是基本类型,所以才看到值相等的两个变量不一定地址也相等

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值