String 中的 equals() 和 ==

String 对象的equals() 与 普通对象的equals()

两个独立的普通对象(不包括基本数据的包装类)使用equals() 来进行比较,不管字段的值是否一样,equals()返回的一定是 false ;

两个独立的String对象(new 创建)使用 equals () 来进行比较,只要它的值一样,返回的一定是 true;

/**
 * 用于测试的普通类
 */
public class User {
    private String name;
    private int age;

    public User() {
    }
    public User(String name) {
        this.name = name;
    }

    // 省略 get, set 方法
}

/**
 * 测试类
 */
public class Test {
    public static void main(String[] args) {
        // 创建两个独立的普通对象
        User user1 = new User("kkk");
        User user2 = new User("kkk");

        // 两个普通对象输出的地址是不一样的
        System.out.println(user1);      // com.zlk.demo1.User@677327b6
        System.out.println(user2);      // com.zlk.demo1.User@14ae5a5
        // 引用类型使用 == 号来比较两个对象的地址值是否一样,即两个引用指向的是否是同一个对象 
        // 由于使用 new 创建对象,jvm会在堆上开辟一块内存来存放对象,所以两个指向的是不同的对象
        System.out.println(user1 == user2);       // false
        // 此处使用的 equals() 是超类(Object)中的方法,判断的也是两个引用指向的是否是同一个对象
        System.out.println(user1.equals(user2));  // false

        System.out.println("------------------- 分割线 -------------------");

        // 创建两个独立的 String 对象, 注意:两个Stirng的值是一样的
        String str1 = new String("kkk");
        String str2 = new String("kkk");

        // 两个值相等的 String 对象的哈希码是一样的
        System.out.println(Integer.toHexString(str1.hashCode()));   // 19f0b
        System.out.println(Integer.toHexString(str2.hashCode()));   // 19f0b
        // str1 和 str2是两个独立的String对象,所以指向的肯定不是同一个对象,返回false
        System.out.println(str1 == str2);       // false
        // 由于是String对象,比较的不仅仅是引用,还比较两个String 对象的值是否一样,
        // 只要这两个条件满足其中一个返回的就是 true 
        System.out.println(str1.equals(str2));  // true
    }

}

为什么两个值相等的普通对象使用equals()比较,返回的是false,而两个String对象使用equals() 比较,返回的却是 true ?

  • 原因是两个普通对象所使用的equals()是超类(Object类)中的方法, 而String 对象使用的是它自己的equals()方法,在String类的底层重写了超类(Object类)的equals() 和 hashCode() 方法。

先看Object类中 equals() 方法的源码(JDK 1.8):

/**
 * 只判断两个引用指向的是否为同一对象
 */
public boolean equals(Object obj) {
    return (this == obj);
}

从源码中可看出,Object类中的 equals() 方法判断的还是两个引用指向的是否为同一对象;


再看 String 类重写equals() 后的源码(JDK 1.8):

/**
 * 对两个字符串对象进行比较
 * 先判断两个引用指向的是否为同一对象, 
 * 如不为同一对象,再判断两个Stirng 对象的值是否一样,
 * 只要两个条件任何一个成立, 即返回 true
 */
public boolean equals(Object anObject) {
    // 先判断两个引用指向的是否为同一对象
    if (this == anObject) {
        return true;
    }
    
    // 如果比较的另一个对象也是String的实例,再对两个String对象的值进行比较
    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;
}

从 String 类中的 equals() 方法可看出,String类的equals() 方法比 Object 类的equals() 方法多了一个值判断;

  • 在 String 类中,equals()方法只要两个String 引用指向同一个对象,或两个String对象的值是一样的,即返回true;
  • 在 Object 类中,equals() 方法只能是两个引用指向同一个对象,才返回true,没有对值进行比较;

== (双等号)

  • 对于基本数据类型,== 号比较的是值;
  • 对于引用类型, == 号比较的是两个对象的地址值是否一样,即两个引用指向的是否是同一个对象
@Test
    public void run1() {
        String str1 = "a" + "b" + "c" + 1 + 2 + 3;
        String str2 = "abc123";
        String str3 = new String("abc123");

        System.out.println(str1 == str2);   	// true
        System.out.println(str2 == str3);   	// false
        System.out.println(str2.equals(str3));  // true
    }

String str1 = “a” + “b” + “c” + 1 + 2 + 3; 由于"a" + “b” + “c” + 1 + 2 + 3 都 是常量值,所以在编译阶段会被编译成str2 = “abc123”; 如果在常量池中没有该字符串,JVM会将其字符串放入常量池;

再到 str2 = “abc123” 时,由于常量池中已有该字符串,所以不会再生成新的字符串,str2 指向的就是常量池中的那个 “abc123”, 所以 str1 == str2 返回 true;

str3 使用 new 来创建字符串对象,JVM 会在堆中开辟一块内存来存放该字符串对象,所以 str3 存放的是堆中的该对象地址,而不是常量池中的(abc123)字符串。str2 指向的是常量池中的字符串,str3 指向的是堆中的对象,所以str2 == str3 返回 false。

String 类重写了equals() 方法,只要两个String 引用指向同一个对象,或两个String对象的值是一样的,即返回true,str2 和 str3 中的值是一样的,所以str2.equals(str3) 返回 true;

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值