Java中==和equals有什么不同是Java面试或笔试中经常看到的题目。这里为了更好的理解和记忆给出==和equals不同点、不同类中equals的源码是怎样的、==和equals测试代码3个方面。

Java中==和equals都有判断对象是否相等的作用,但是它们的用法并不相同。

==和equals不同点

  • 属性不同:==是操作符;equals是方法。
  • 用法不同:==比较的是地址或基本数据类型;equals比较的是对象的地址(对于String类型,equals比较的是String的内容)。
  • 范围不同:==既可以比较基本数据类型和也可以比较引用数据类型;equals是方法只能比较引用数据类型。

注意:==两边是基本数据类型时,比较的是值是否相等,相等返回true,否则返回false;==两边比较的是引用类型时,则比较的是地址是否一样,相同地址则返回true,不同地址返回false。而equals比较的是对象的地址,对于String类型,equals比较的是String的内容。

equals的源码

下面给出Java中equals方法在各个类中的源码,其中String类中的比较若有不同。

String类中的equal()方法源码

public boolean equals(Object anObject) {
    //判断是否是同一个对象,如果是的话就返回true
        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;
    } 

Object类中的equals方法源码

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

Byte包装类中equals方法源码

public boolean equals(Object obj) {
     if (obj instanceof Byte) {
         return value == ((Byte)obj).byteValue();
     }
     return false;
} 

Short包装类中equals方法源码

 public boolean equals(Object obj) {
        if (obj instanceof Short) {
            return value == ((Short)obj).shortValue();
        }
        return false;
} 

==和equals代码测试

下面给出==和equals测试代码

//创建2个String对象
String s1 = new String("yxjc123");
String s2 = new String("yxjc123");
// == 比较的是2个地址,其中s1和s2在内存中的地址不同
System.out.println(s1==s2);//false
// equals方法在String中比较的是对象内容
System.out.println(s1.equals(s2));//true

String s3 = "yxjc123";
String s4 = "yxjc123";
// s3和s4都是引用数据类型,但"yxjc123"是保存在常量池中的,它们都指向的是常量池中同一个地址
// 所以 == 符号操作符 s3和s4相等
System.out.println(s3 == s4);//true
// 同样是比较两个地址,s3指向的是常量池中的地址,s1指向的是堆中的地址。
System.out.println(s3 == s1);//false

String s5 = "yxjc123yxjc123";
String s6 = s3 + s4;
// s5保存的是指向常量池的地址;s6保存的是指向堆中对应对象的空间,因为字符串是不可变对象,
// 无法直接通过相加而相连接,所以在进行相加操作时,实际上做的是:创建一个新的字符串对象,
// 通过 new StringBuilder()来创建。结果是false
System.out.println(s5 == s6);//false

final String s7 = "yxjc123";
final String s8 = "yxjc123";
String s9 = s7 + s8;
// final关键字修饰后,s7和s8都由变量变为了常量,编译器处理常量运算时会作出优化,
// 将运算后的结果转为常量, 然后再将常量结果赋给s9。下面语句结果为true
System.out.println(s9 == s5);//true

final String s10 = s3 + s4;
// s3 + s4是两个字符串对象相加,它们通过 new StringBuilder() 创建一个新的对象,然后
// 将此对象的地址给 s10, 然后final关键字将s10转为常量,但s10始终保存的是指向堆中的地址
// s5是指向常量池的地址。下面语句结果为false.
System.out.println(s5 == s10);//false

测试一下