==和equals方法

Java程序中测试两个变量时否相等有两种方法: == 和 equals。

==判断

当使用==来判断两个变量是否相等时,如果两个变量是基本类型变量,且都是数字类型(不一定要求数据类型严格相同),则只要两个变量的值相同,就将返回true。
但对于两个引用类型变量,只有它们指向同一个对象时,== 判断才会返回true。
== 不可用于比较类型上没有父子关系的两个变量。

public static void main(String[] args) {
        int i = 65;
        float f = 65.0f;
        // 输出true
        System.out.println("65和65.0f是否相等?" + (i == f));

        char c = 'A';
        // 输出true
        System.out.println("65和'A'是否相等?" + (i == c));

        String s1 = new String("Test");
        String s2 = new String("Test");
        // 输出false
        System.out.println("s1和s2是否相等?" + (s1 == s2));
        // 输出true
        System.out.println("s1和s2是否相等?" + (s1.equals(s2)));

        // 编译不过
        // System.out.println("Test" == new EqualTest());
    }

需要注意 "Test"和new String("Test")是有区别的?

  “Test”是字符串直接量(即可以在编译时就计算出来的字符串值),JVM使用常量池来管理这些字符串,

  当使用new String("Test")时,JVM先使用常量池来管理“Test”直接量,再调用String类的构造器来创建一个新的String对象,新创建的String对象被保存在堆内存中。也就是说new String("Test")一共创建了两个字符串对象。

常量池(constant pool)专门用来管理在编译时被确定并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口中的常量,还包括字符串常量。

public static void main(String[] args) {
        String s1 = "Hello";
        String s2 = "H";
        String s3 = "ello";
        // 不能在编译时确定
        String s4 = s2 + s3;
        // 在编译时就确定下来了,直接引用常量池中的“Hello”
        String s5 = "H" + "ello";
        // 引用内存中新创建的String对象
        String s6 = new String("Hello");

        // true
        System.out.println(s1 == s5);

        // false
        System.out.println(s1 == s4);

        // false
        System.out.println(s1 == s6);
    }

equals判断

equals()方法是Object类提供的一个实例方法,因此所有的引用变量都可以调用该方法来判断是否与其他引用变量相等。

判断两个对象相等时,和==运算符没有区别,同样要求两个引用变量指向同一个对象才返回true。因此Object提供的equals方法没有太大的意义,可以重写equals()方法实现。

注意,String已经重写了equals()方法,只要两个字符串所包含的字符串序列相同,则返回true。

笼统的说equals()方法是判断两个对象的值相等,这样的说法并不准确。

public class EqualsTest {
    public static void main(String[] args) {
        Person p1 = new Person("小王", "1234");
        Person p2 = new Person("王二", "1234");
        Person p3 = new Person("小王", "12345");

        // true
        System.out.println(p1.equals(p2));
        // false
        System.out.println(p1.equals(p3));
    }
}

class Person {
    private String name;
    private String idStr;

    public Person() {

    }

    public Person(String name, String idStr) {
        this.name = name;
        this.idStr = idStr;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getIdStr() {
        return idStr;
    }

    public void setIdStr(String idStr) {
        this.idStr = idStr;
    }

    // 重写equals方法,自定义两个对象相等的条件
    public boolean equals(Object obj) {
        // 如果两个对象是同一个对象
        if (this == obj) {
            return true;
        }

        // 只有当obj对象是Person对象
        if (obj != null && obj.getClass() == Person.class) {
            Person personObj = (Person) obj;
            // 并且当前对象的idStr和obj对象的idStr相等时,才判断两个对象相等
            if (this.getIdStr().equals(personObj.getIdStr())) {
                return true;
            }
        }

        return false;
    }
}

正确的重写equals()方法,应该满足下列条件:

1. 自反性:对任意的x,x.equals(x)一定返回true。

2. 对称性:对任意x, y,如果x.equals(y)返回true,则y.equals(x)返回true。

3. 传递性:对任意x, y, z,如果x.equals(y)返回true,y.equals(x)返回true,则x.equals(z)也返回true。

4. 一致性:对任意x, y,如果对象中用于等价比较的信息没有改变,那么无论x.equals(y)多少次,返回的结果应该保持一致,要么一直是true,一直是false。

5. 对任何不是null的x, x.equals(null)一定返回false。

Object默认提供的equals()只是比较对象的地址,即Object类的equals()方法比较的结果与==运算符比较的结果完全相同。因此,在实际应用中常常需要重写equals()方法,相等的条件是由业务要求决定,因此equals()方法的实现也是由业务要求决定。

 

转载于:https://www.cnblogs.com/FocusIN/p/6746759.html

### Java 中 `==` 运算符与 `equals()` 方法的区别 #### 基本概念 在Java中,`==` `equals()` 是两种不同的比较方式。`==` 主要用于基本数据类型对象引用的比较,而 `equals()` 则主要用于对象内容的比较。 #### 对于基本数据类型的比较 当使用 `==` 来比较两个基本数据类型时,它会直接比较这两个值是否相等[^3]。 ```java int a = 5; int b = 5; System.out.println(a == b); // true, 因为数值相同 ``` #### 对象引用的比较 (`==`) 对于对象来说,如果使用 `==` 比较,则是在检查两个变量所指向的对象是否位于相同的内存位置,即它们是否是指向同一个实例。这意味着即使两个不同对象具有完全相同的内容,只要不是同一个实例,那么用 `==` 比较的结果就是 false[^1]。 ```java String str1 = new String("test"); String str2 = new String("test"); System.out.println(str1 == str2); // false, 不同实例 ``` 但是需要注意的是,在某些情况下(如字符串字面量),由于JVM优化可能会让多个看起来独立创建却拥有相同字符序列的字符串共享同一份存储空间,这时即使是新创建的不同对象也可能返回 true 的情况存在例外[^2]: ```java String s1 = "hello"; String s2 = "hello"; System.out.println(s1 == s2); // true, 字符串常量池中的重复利用 ``` #### 使用 `equals()` 方法进行内容比较 相比之下,`equals()` 方法通常被用来判断两个对象的实际内容是否一致而不是仅仅基于其引用地址。默认情况下,`Object` 类提供的 `equals()` 实现实际上只是简单调用了 `==` 来执行浅层对比;然而许多标准库类已经覆盖并重新实现了此方法以便更合理地反映逻辑上的平等关系——例如 `String`, `Integer` 等类都会根据各自的数据成员来进行深层次的内容匹配。 ```java // 自定义类重写 equals() public class Person { private final String name; public Person(String name) { this.name = name; } @Override public boolean equals(Object o) { if (this == o) return true; // 首先处理自反性 if (!(o instanceof Person)) return false; // 排除其他类型 Person person = (Person) o; return Objects.equals(name, person.name); } } Person p1 = new Person("Alice"); Person p2 = new Person("Alice"); System.out.println(p1.equals(p2)); // true, 内容相同 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值