Java中的 == 和 equals 区别

Java中的 == 和 equals 到底有什么区别?

  1. 提到Java的 == 和 equals,很多人就会说 == 比较的值(地址), equals比较内容,这句话到底对不对?
    equals是object类的一个方法,定义如下:
    public boolean equals(Object obj) {
    return (this == obj);
    }
    我们看到,当调用equals时, 实际还是调用了 == ,而 == 操作符 当且仅当 左右两端的值相等时返回true,那么我们常说的equals比较内容又有错吗?错在哪里?
    实际上我们口中说的比较内容大都是说String类,String类重写了Object的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;
    }
    我们看到,String的equals方法同样先 == 判断,如果值相等返回true,否则将比较对象转成String(此处讲解String比较),而后比较它们的字符序列,这就是常说的“内容”, equals方法相对简单,不做过多讲解。
    2. 为什么Java中字符串比较都用equals而不用 ==
    上面已经讲到字符串的equals方法,几个字符串 == 比较的示例代码,读者可以不看答案自己心里先思考一下是否相等,看看自己是否理解了 字符串的 == 操作。
    public static final String str0 = “abcde”;
    public static void main(String[] args) {
    String strObj = new String(“abc”);
    String strObj1 = new String(“abc”);
    String strObj2 = new String(“de”);
    String str1 = “abc”;
    String str2 = “de”;
    final String str3 = “abc”;
    final String str4 = “de”;
    System.out.println(strObj == strObj1);//false
    System.out.println(strObj.intern() == strObj1.intern()); //true
    System.out.println((strObj1 + strObj2) == str0); //false
    System.out.println((str1 + str2) == str0);//false
    System.out.println((str1 + str2).intern() == str0);//true
    System.out.println((str3 + str4) == str0);//true
    System.out.println((str3 + str4).intern() == str0); //true
    首先 new String 操作会在堆上创建一个String对象,若字符串常量池中没有此字符串则也会在常量池中放一份,这里也有一道面试题String a = “a”;和String a = new String(“a”)有什么区别,区别就是前者创建一个后者则会创建两个, 所以这里第一个就会返回false。
    在这里插入图片描述
    String.intern方法,如果常量池中已有此对象则返回该对象的引用, 如果没有则在常量池中放一份并返回该引用。因此,strObj.intern()时常量池没有,会放入“abc”,并返回该引用,而strObj1.intern()时常量池中已有该字符串,则直接返回该引用,因此地址值相等,返回true。
    第三行,被 String类对+操作符的重载导致字符串相加实际上是创建了StringBuilder对象的append方法之后调用ToString()实现的,因此等同于:
    new StringBuilder().append(strObj1).append(strObj2).toString(),显然是false。
    第四行,和第三行一样,返回false。
    第五行,有了前面的基础,第五行可以看作是"abcde".intern() == “abcde”,这样返回true就不难理解了,因为字符串”abcde“已经存在,直接返回引用。
    第六行,这里注意,与前面的区别是final修饰符,被final修饰的不可变量会在编译期优化掉,因此第六行编译期间就会"知道" str3 + str4实际上是"abcde"。
    第七行在第六行的基础上已经是显而易见了。
    实际上,字符串字面量相加也会被编译优化,例如 String test = “abc” + “de”;也会在编译期被认为String test = “abcde”;因此,如果声明了这个test,则test == str0和 (“abc” + “de”)== str0都会返回true。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值