equals()和==的比较

本文详细解析了equals()方法与==操作符的区别及应用场景,包括它们在Java中的默认行为、如何在String类中被重写,以及不同类型的对象比较。

转载   http://blog.youkuaiyun.com/u013054285/article/details/78985798

1.equals()和==是什么?

equals():是方法,定义在超类Object中的一个方法,用来比较两个对象。 
==:是操作符,用来比较两个对象。

为什么会将一个操作符和一个方法进行比较呢? 
因为它们都是用来比较两个对象的,但它们在用法上又有些区别。 
这些区别如果不稍加注意,在开发的过程中就很容易翻车。

个人理解:
==和equals()作用是相同的。
但是equals()是一个方法,可以重写equals()方法,实现不同的作用。比如String类中的eqauls()方法。

2.为什么说它们是一样的?

我们来看一下Object中是如何实现eqauls()方法,代码如下:

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

很明显,在源代码中,equals()方法返回的就是使用 == 比较两个对象后的结果。 
从这个角度来说,我认为它们的作用是一样的,都是用来比较两个对象的引用的。

3.它们的区别在哪?

最直观的来看,==是操作符,eqauls()是超类Object中的方法,这是最基本的区别。 
正是由于这个区别,才有了== 和eqauls()的不同用法。 
首先,eqauls()方法是超类Object中的方法,而Java中所有的对象都是继承自Object类的,所以子类是可以重写eqauls()方法而实现不同的功能。 
最典型的就是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;
}通过代码我们发现,String重写了equals()方法,从引用地址比较变成引用内容的比较。

4.栗子

4.1.第一个栗子:

我们先来比较下基本数据类型:

public static void main(String[] args) {
    int a = 3;
    int b = 3;
    System.out.println(a == b);
}
console:
true

对8种基本数据类型使用==比较。

Tips:首先基本数据类型不是对象,也就不是Object类的子类了,所以没有equals()方法。 
但是这好像又违反了Java的“一切都是对象”的准则,所以,Java就给基本数据类型提供了包装类型。

4.2.第二个栗子:

我们来比较下String类型:

public static void main(String[] args) {
    String str1 = "abc";
    String str2 = new String("abc");
    System.out.println(str1 == str2);
    System.out.println(str1.equals(str2));

    String str3 = "abc";
    System.out.println(str1 == str3);
    System.out.println(str1.equals(str3));
}
console:
false
true
true
true

String类型为什么会产生这种结果呢? 
首先我们来了解String的两种创建方式:

  • 使用引号创建:创建的对象会存放在字符串缓冲池中。当创建str1时,JVM会在字符串缓冲池中寻找”abc”,没有找到,则创建”abc”,然后将str1指向”abc”。创建str2的过程和创建str1是一样的,只不过此时字符串缓冲池中包含了”abc”,则直接将str2指向”abc”。
  • 使用new创建:使用new来创建对象,存放在堆中,而且每次都会重新创建一个对象。

再结合我们对 == 和equals()的分析,以及String类对equals()的重写,我们很容易就会明白为什么会是这种结果了。

Tips: String类提供了一个intern()的方法。如果对str2使用intern()方法,代码如下:

public static void main(String[] args) {
    String str1 = "abc";
    String str2 = new String("abc");
    str2 = str2.intern();
    System.out.println(str1 == str2);
    System.out.println(str1.equals(str2));
}
console:
true
true

为什么会产生这种结果呢?我们来看下官方是怎么说的。 
在String类的源码中,我们找到intern()方法,官方提供了一段注释,其中有一段是这么写的

/* When the intern method is invoked, if the pool already contains a
* string equal to this {@code String} object as determined by
* the {@link #equals(Object)} method, then the string from the pool is
* returned. Otherwise, this {@code String} object is added to the
* pool and a reference to this {@code String} object is returned.
*/

大概意思就是说:调用intern()方法的时候,会首先查找缓冲池中是否有这个字符串,如果有,直接返回;如果没有,则在缓冲池中创建这个字符串,然后返回对象的引用。

4.3.第三个栗子:

我们首先定义一个Cat类

public class Cat {
}

然后我们在方法中进行比较:

public static void main(String[] args) {
    Cat cat1 = new Cat();
    Cat cat2 = new Cat();
    System.out.println(cat1 == cat2);
    System.out.println(cat1.equals(cat2));

    Cat cat3 = cat1;
    System.out.println(cat1 == cat3);
    System.out.println(cat1.equals(cat3));
}
console:
false
false
true
true

首先我们创建了cat1对象,并在堆中为其分配了一块地址,而cat1存储的是指向这块地址的引用。 
然后我们创建了cat2对象,和cat1一样,在堆中分配了一块地址,然后cat2存储了指向这块地址的引用。 
这样,我们在堆中有了两个Cat类的实例对象。而根据==和equals()的规则,cat1和cat2的比较自然不相同。 
在创建cat3的时候,我们直接将cat1赋值给了cat3,则cat3中也是存储了和cat1一样的地址。

5.什么时候用?

==:通常我们用在基础数据类型的比较上,因为基础类型的特殊性,所以可以直接使用==来比较基础数据类型的值。同时我们也可以用来比较两个对象是不是同一个对象。 
equasl():我们通常用来比较两个对象,或者用来比较String对象的内容。更重要的是,如果有特殊的业务需求,我们可以重写equasl()方法,来实现我们的目的。

6.结语

在equals()和==的比较中,其实涉及到很多JVM内存的知识。关于内存的问题,我会在后期专门写出来和大家分享的。 
关于equals()和==的比较,我已经简单的说完了,但是由于个人水平有限,其中难免会出现不够严谨和错误的地方,希望大家不吝赐教。

<think>好的,我现在需要回答用户关于Java中equals方法==运算符的区别及使用场景的问题。首先,我需要回顾已有的知识,并结合用户提供的引用资料来确保答案的准确性。 用户引用了四个资料,其中引用[2]、[3]、[4]都是关于Java中equals==的区别,而引用[1]是关于C#的,可能可以忽略,因为用户的问题集中在Java上。我需要仔细阅读这些引用内容,提取关键点。 首先,根据引用[2],==比较的是对象的引用(地址),而equals默认比较的也是引用,但可以重写来比较内容。此外,==是运算符,equals是方法,==速度更快。引用[3]补充了对于基本数据类型,==比较值,对于对象则是地址;而String类的equals比较字符序列。引用[4]则提供了如何重写equals方法的例子,强调自定义对象内容比较时需要重写equals。 接下来,我需要组织这些信息,分点说明区别使用场景。可能需要分为功能差异、比较对象类型、性能、以及使用场景几个部分。同时,需要举例说明,比如字符串比较的例子,以及自定义对象的例子,这样用户更容易理解。 需要注意的是,用户可能对基本数据类型引用类型的区别不太清楚,需要明确说明。例如,==在基本类型时比较值,在引用类型比较地址;而equals用于对象内容比较,但默认行为需要重写。 另外,要确保使用正确的中文术语,避免技术术语错误。比如,“引用”“地址”需要准确对应。同时,检查是否有遗漏点,比如String类的特殊情况,以及如何正确重写equals方法,包括处理null类型检查等步骤。 最后,生成相关问题,可能需要包括为什么String的equals比较内容,如何正确重写equals方法,以及何时使用==equals的场景例子等。</think>### Java中equals方法与==运算符的区别及使用场景 #### 一、核心区别 1. **功能差异** - `==` 是**运算符**,用于比较两个变量的**存储地址是否相同**(引用类型)或**值是否相等**(基本数据类型)[^2][^3]。 - `equals()` 是**方法**,默认实现与 `==` 相同(比较地址),但可通过重写实现**对象内容的比较**[^4]。 2. **适用对象类型** - **基本数据类型**(如 `int`, `char`):只能用 `==` 比较值。 - **引用类型**(如 `String`, 自定义类): - `==` 比较对象的内存地址。 - `equals()` 比较对象内容(需重写方法)[^3][^4]。 3. **性能差异** - `==` 直接比较地址或值,速度更快。 - `equals()` 可能涉及复杂逻辑(如遍历字符串字符),效率较低[^3]。 #### 二、典型示例 1. **字符串比较** ```java String s1 = new String("hello"); String s2 = new String("hello"); System.out.println(s1 == s2); // false(地址不同) System.out.println(s1.equals(s2)); // true(内容相同)[^3] ``` 2. **自定义对象** ```java class Person { String name; int age; @Override public boolean equals(Object obj) { if (this == obj) return true; // 地址相同直接返回true if (obj == null || getClass() != obj.getClass()) return false; Person p = (Person) obj; return age == p.age && name.equals(p.name); // 比较内容[^4] } } ``` #### 三、使用场景 | **场景** | **使用方式** | **说明** | |-------------------------|--------------------|-----------------------------| | 基本数据类型比较 | `==` | 如 `int a=5; if(a == 5)` | | 引用类型地址比较 | `==` | 判断是否为同一个对象实例 | | 对象内容比较(如String) | `equals()` | 需确保类已正确重写equals方法 | | 自定义对象内容比较 | 重写`equals()` | 需同时重写`hashCode()`方法 | #### 四、注意事项 1. **重写`equals()`的规范**: - 自反性:`x.equals(x)` 必须为 `true`。 - 对称性:若 `x.equals(y)` 为 `true`,则 `y.equals(x)` 也需为 `true`。 - 一致性:多次调用结果不变(不依赖可变状态)。 - 非空性:`x.equals(null)` 必须为 `false`[^4]。 2. **`hashCode()`的关联**: 重写 `equals()` 时必须同时重写 `hashCode()`,以确保在哈希表(如 `HashMap`)中行为一致。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值